例文を使って繰り返し業務を時短

【マクロ・VBA】右のシートに無いデータチェック_ディクショナリ

エクセル、マクロ、VBAでDictionaryを使ってアクティブシートと右隣のシートの差異を調べる方法 VBA

アクティブシートと右隣りのシートの差異をディクショナリで調べる

このVBAコードは、エクセルのアクティブなシートとその右にあるシートを比較して、右側のシートに存在しない行があるかどうかをチェックするためのものです。

<操作概要>

  1. アクティブシートとアクティブシートの右隣りのシートに差異を調べたいデータを準備
  2. アクティブシートの右隣りのシートの最終列に1を代入
    ⇒一列目をキーに最終列をアイテムに代入
  3. アクティブシートのキーに設定している1列目とアクティブシートの右隣りのシートのキーをディクショナリでマッチングして、マッチしなかったデータをアクティブシートの最終列に「-1」を代入
Sub 右のシートに無いデータチェック_ディクショナリ() 

Dim sheet_1 As Worksheet, sheet_2 As Worksheet
Set sheet_1 = ActiveSheet
Set sheet_2 = ActiveSheet.Next

Dim LastLow1 As Long, LastLow2 As Long, LastCol1 As Long, LastCol2 As Long
LastLow1 = sheet_1.Cells(Rows.Count, 1).End(xlUp).Row
LastCol1 = sheet_1.Cells(2, Columns.Count).End(xlToLeft).Column    
LastLow2 = sheet_2.Cells(Rows.Count, 1).End(xlUp).Row
LastCol2 = sheet_2.Cells(2, Columns.Count).End(xlToLeft).Column     

Dim myDic As Object, myKey
Dim c, myVal
Dim i As Long
Set myDic = CreateObject("Scripting.Dictionary")


'相手のシート(アクティブシートの右隣り)
On Error Resume Next
For i = 2 To LastLow2
    sheet_2.Cells(i, LastCol2 + 1).Value = 1
         
    If Not myDic.Exists(sheet_2.Cells(i, 1).Value) Then                                           
       myDic.Add (sheet_2.Cells(i, 1).Value), (sheet_2.Cells(i, LastCol2 + 1).Value)        
    End If
Next i

'基のシート(アクティブシート)の最終列の後ろに転記
For i = 2 To LastLow1
        
    If Not myDic.Exists(sheet_1.Cells(i, 1).Value) Then
       sheet_1.Cells(i, LastCol1 + 1).Value = Not myDic.Item(sheet_2.Cells(i, LastCol2 + 1).Value) 
    End If

Next i
    
On Error GoTo 0

Cells.AutoFilter Field:=1

Set myDic = Nothing
Set sheet_1 = Nothing
Set sheet_2 = Nothing

ActiveSheet.Cells(1, LastCol1).Select

MsgBox "完了"
End Sub

解説

まず、2つのシートを変数 sheet_1sheet_2 にセットします。そして、それぞれのシートの最終行と最終列を LastLow1LastCol1LastLow2LastCol2 という変数にセットします。

次に、空のディクショナリー myDic を作成し、右側のシートのデータを読み込みながら、各行の最後の列に「1」を設定します。その後、各行の1列目の値を myDic に追加します。もし、1列目の値が既に myDic に存在している場合は、追加せず、その行の最後の列に「1」をセットします。

その後、左側のシートの各行の1列目の値を myDic でチェックし、存在しない場合は、その行の最後の列に「True」を設定します。ここで、右側のシートの最後の列に設定された「1」を使って、左側のシートで新しく設定する列のデータを作成します。

最後に、 myDic をクリアし、自動フィルターを適用して、最後の列を選択し、完了メッセージを表示します。

このコードの速度を向上させるために、 ActiveSheetActiveSheet.Next の代わりに、明示的にシート名を指定することができます。また、シートの最終行と最終列をセットする際に、UsedRange を使って実行することができます。最後に、ディクショナリーの要素を追加する前に、If ステートメントを使って存在チェックを行うことができます。これにより、重複を防止し、処理速度が向上します。

上記コードのスピードアップ改善コード

Sub 右のシートに無いデータチェック_ディクショナリ2() 

Dim sheet_1 As Worksheet, sheet_2 As Worksheet
Set sheet_1 = ThisWorkbook.Worksheets("シート1")
Set sheet_2 = ThisWorkbook.Worksheets("シート2")

Dim LastLow1 As Long, LastLow2 As Long, LastCol1 As Long, LastCol2 As Long
LastLow1 = sheet_1.Cells(sheet_1.Rows.Count, 1).End(xlUp).Row
LastCol1 = sheet_1.Cells(2, sheet_1.Columns.Count).End(xlToLeft).Column
LastLow2 = sheet_2.Cells(sheet_2.Rows.Count, 1).End(xlUp).Row
LastCol2 = sheet_2.Cells(2, sheet_2.Columns.Count).End(xlToLeft).Column

Dim myDic As Object, myKey
Dim c, myVal
Dim i As Long
Set myDic = CreateObject("Scripting.Dictionary")

'相手のシート(アクティブシートの右隣り)
On Error Resume Next
For i = 2 To LastLow2
    sheet_2.Cells(i, LastCol2 + 1).Value = 1
     
    If Not myDic.Exists(sheet_2.Cells(i, 1).Value) Then
        myDic.Add sheet_2.Cells(i, 1).Value, sheet_2.Cells(i, LastCol2 + 1).Value
    End If
Next i

'基のシート(アクティブシート)の最終列の後ろに転記
For i = 2 To LastLow1
    
    If Not myDic.Exists(sheet_1.Cells(i, 1).Value) Then
        sheet_1.Cells(i, LastCol1 + 1).Value = Not myDic.Item(sheet_1.Cells(i, LastCol1).Value)
    End If
    
Next i

On Error GoTo 0

sheet_1.Cells.AutoFilter Field:=1

Set myDic = Nothing
Set sheet_1 = Nothing
Set sheet_2 = Nothing

ThisWorkbook.Worksheets("シート1").Cells(1, LastCol1).Select

MsgBox "完了"
End Sub

変更点は次のとおりです。

  1. シートの明示的な指定

ActiveSheet や ActiveSheet.Next ではなく、ThisWorkbook.Worksheets(“シート名”) を使用して、シートの明示的な指定を行いました。

  1. 要素の存在チェックの追加

ディクショナリーに要素を追加する前に、If ステートメントを使用して、myDic.Exists() メソッドを呼び出して、要素が存在しないかどうかをチェックするようにしました。

  1. コードの修正

次のコードを修正しました。

  • myDic.Add (sheet_2.Cells(i, 1).Value), (sheet_2.Cells(i, LastCol2 + 1).Value) を myDic.Add sheet_2.Cells(i, 1).Value, sheet_2.Cells(i, LastCol2 + 1).Valueに変更

アクティブシートと右隣りのシートの差異をディクショナリで調べる

* 右隣りのシートにあり、アクティブシートにないデータをメッセージボックス
 に表示/出力シートに表示

Sub シート間_ディクショナリ()

Dim vList As Object
Dim vName As String
Dim i As Long
    
'チェック用のリストを作成する
Set vList = CreateObject("Scripting.Dictionary")
    
    '「突合」ワークシートに対して処理を行う
    With ActiveSheet
        On Error Resume Next
        
        For i = 2 To .Range("A1").CurrentRegion.Rows.Count
            DoEvents
            vList.Add .Cells(i, 1).Value, .Cells(i, 3).Value
        Next
        
        On Error GoTo 0
    End With
    
    
    '「相手」ワークシートに対して処理を行う
    With ActiveSheet.Next
        
        On Error Resume Next
        
        For i = 2 To .Range("A1").CurrentRegion.Rows.Count
            DoEvents
            
            If Not vList.Exists(.Cells(i, 1).Value) Then
                
                vName = vName & .Cells(i, 1).Value & vbCrLf
                
            End If
        Next

        ThisWorkbook.Worksheets("出力").Cells(1, 1).Value = vName  'スピリットでセルに代入
        
        On Error GoTo 0
    End With
    
MsgBox vName
End Sub

コメント

タイトルとURLをコピーしました