この記事は、複数の列を比べて重複行を探す、というものです。

「単独の列で重複している行を探す」というサンプルは、
VBAのお勉強 VBAでExcelの重複した行を探して表示
をご覧下さい。
「重複している行を1行だけ残して削除する」というサンプルは、
VBAのお勉強 Excelで1行残して重複行を削除
をご覧下さい。

http://q.hatena.ne.jp/1205154937

「列単位でコンペアさせ、コンペア結果、重複データがある場合」という条件がはっきりしないので、

勝手に「Sheet1のA列のある行のデータがSheet2のA列のどこかにあった場合、重複データとする」としてみました。

イメージとしては、

  • Sheet1のA列の1行目の値を取り、その値がSheet2のA列にあるかどうかを調べる。
  • あったらその値をSheet3に書き出す、なければそのまま。
  • これをSheet1の最後の行まで繰り返す。

という感じでしょうか。

例えばこんな感じのワークシートがあったとします。

02.jpg04.jpg

まずSheet1のA列の1行目の値「a」に注目します。

この値がSheet2のA列の1~7行目にあれば、Sheet3に書き出します。

この場合、「a」はありませんので何もしません。

次、Sheet1の2行目の「b」。これもないので何もしません。

次、Sheet1の3行目の「c」。これはSheet2のA列の1行目にありますので、 Sheet3に書き出します。

書き出す位置は、これが見つかった値の1個めですからA1にします。

次、Sheet1の4行目の「1」。これもないので何もしません。

次、Sheet1の5行目の「2」。これもないので何もしません。

次、Sheet1の6行目の「3」。これはSheet2のA列の4行目にありますので、 Sheet3に書き出します。

書き出す位置は、これが見つかった値の2個めですからA2にします。

これでSheet1の全部の行を見ました。

これでおっけい(^^)

ではこれをプログラムにしてみます。

Excelから「ツール」→「マクロ」→「Visual Basic Editor」でプロジェクトの中の「Sheet1」をダブルクリック、するとコードを記述するウィンドウが表示されます。

まず、Sheet1のA列を一行ずつ見ていく必要があるので、とりあえず、イミディエイトウィンドウに Sheet1のA列を1行ずつ表示するプログラムを作ってみます。

この記事でやったことと全く同じですね(^^;)

Sub test()

    Dim lastgyou As Integer
    Dim i        As Integer
    
    ActiveSheet.Range("A1").End(xlDown).Select
    lastgyou = ActiveCell.Row
    
    For i = 1 To lastgyou
        
        Debug.Print (ActiveSheet.Cells(i, 1).Value)
    
    Next

End Sub

で、実行してみます。

  06.jpg

ん、いいんでないかい(^^)

次、こうやって取り出した値を1つずつ、Sheet2にあるかどうかを探す事になりますので、 Sheet2も同じように、A列の何行目までデータが入っているかを調べてみます。

。。。はて。上のプログラムだと、ActiveSheetってなってますので、今現在選択しているシートの事しかわからないですね。

というか、これじゃ、このプログラムを実行したときに選択されているシートの値を表示しちゃうかな?

試しに、Sheet2を選択した状態でこのプログラムを動かしてみると、

  08.jpg

(^^;)Sheet2の値が表示されちゃいました。

これじゃ駄目ですね。 どうしたもんか。。。

どのシートが選択されている状態でもSheet1の値を見るようにしないとまずいですね。

プログラムでシートを選択する方法を調べてみます。

Yahoo!で「vba excel シートの選択」で検索すると、こちらのページが見つかりました。

Sheets(“Sheet1″).Select で良いみたいですね。 これをプログラムの先頭に入れてみます。

Sub test()
    
    Dim lastgyou As Integer
    Dim i        As Integer
    
    Sheets("Sheet1").Select
    ActiveSheet.Range("A1").End(xlDown).Select
    lastgyou = ActiveCell.Row
    
    For i = 1 To lastgyou
        
        Debug.Print (ActiveSheet.Cells(i, 1).Value)
    
    Next

End Sub

Sheet2を選択した状態で、

  10.jpg

プログラムを実行してみます。

12.jpg

ん、Sheet1に切り替わってますね。いいかんじ(^^)

Sheet2について調べたければ Sheets(“Sheet2″).select に切り替えればいいですね。

それでは、Sheet1とSheet2、それぞれ何行目までデータが入っているかを調べてみます。

Sub test()
    
    Dim sheet1lastgyou As Integer
    Dim sheet2lastgyou As Integer
    
    Sheets("Sheet1").Select
    ActiveSheet.Range("A1").End(xlDown).Select
    sheet1lastgyou = ActiveCell.Row
    
    Sheets("Sheet2").Select
    ActiveSheet.Range("A1").End(xlDown).Select
    sheet2lastgyou = ActiveCell.Row
    
    Debug.Print ("sheet1は" + Str(sheet1lastgyou) + "行目まで")
    Debug.Print ("sheet2は" + Str(sheet2lastgyou) + "行目まで")

End Sub

Sheet1の最終行の行番号がsheet1lastgyouに入り、Sheet2がsheet2lastgyouです。

14.jpg

ん、よいようです(^^)

それではとりあえず、Sheet1のデータがSheet2にあるかどうかを調べるプログラムを作ってみます。

Sub test()

    Dim i              As Integer
    Dim j              As Integer
    Dim check          As String
    Dim sheet1lastgyou As Integer
    Dim sheet2lastgyou As Integer
    
    'Sheet1の最終行を求める
    Sheets("Sheet1").Select
    ActiveSheet.Range("A1").End(xlDown).Select
    sheet1lastgyou = ActiveCell.Row
    
    'Sheet2の最終行を求める
    Sheets("Sheet2").Select
    ActiveSheet.Range("A1").End(xlDown).Select
    sheet2lastgyou = ActiveCell.Row
    
    'Sheet1を1行目から最終行まで
    For i = 1 To sheet1lastgyou
        
        'Sheet1を選択します
        Sheets("Sheet1").Select
        
        'Sheet1のi行目の値を取り出します
        check = ActiveSheet.Cells(i, 1).Value
        
        'Sheet2を選択します
        Sheets("Sheet2").Select
        
        'Sheet2を1行目から最終行まで
        For j = 1 To sheet2lastgyou
            
            'Sheet2のj行目の値とcheckの値が同じだったら
            If ActiveSheet.Cells(j, 1).Value = check Then
                
                'とりあえずイミディエイトウィンドウに表示します
                Debug.Print (check)
            
            End If
        
        Next
    Next
End Sub

プログラムにコメントを入れてみました。やってることは、さっき言葉で書いたことそのままです。

動かしてみます。

14_2.jpg

ん、重複している値(「c」と「3」)が表示されました(^^)

あとは、この見つけた値をSheet3に書き出していけばいいですね。

1つ目を見つけたら、Sheet3のA1にその値を入れる、

2つ目を見つけたら、Sheet3のA2にその値を入れる、

以下繰り返しって感じで。

今何個目なのかを入れておく変数を作り、見つけたら、セルに値を入れ、変数を1つ増やす、これで行きます。

Sub test()
    Dim i              As Integer
    Dim j              As Integer
    Dim check          As String
    Dim sheet1lastgyou As Integer
    Dim sheet2lastgyou As Integer
    Dim sheet3gyou     As Integer
    
    'Sheet1の最終行を求める
    Sheets("Sheet1").Select
    ActiveSheet.Range("A1").End(xlDown).Select
    sheet1lastgyou = ActiveCell.Row
    
    'Sheet2の最終行を求める
    Sheets("Sheet2").Select
    ActiveSheet.Range("A1").End(xlDown).Select
    sheet2lastgyou = ActiveCell.Row
    
    'Sheet3の行数を0にしておく
    sheet3gyou = 0
    
    'Sheet1を1行目から最終行まで
    For i = 1 To sheet1lastgyou
        
        'Sheet1を選択します
        Sheets("Sheet1").Select
        
        'Sheet1のi行目の値を取り出します
        check = ActiveSheet.Cells(i, 1).Value
        
        'Sheet2を1行目から最終行まで
        For j = 1 To sheet2lastgyou
            
            'Sheet2を選択します
            Sheets("Sheet2").Select
            
            'Sheet2のj行目の値とcheckの値が同じだったら
            If ActiveSheet.Cells(j, 1).Value = check Then
                
                'Sheet3に代入するセルの行数を1つ増やします。
                sheet3gyou = sheet3gyou + 1
                
                'Sheet3を選択します
                Sheets("Sheet3").Select
                
                'セルに見つけた値を代入します
                ActiveSheet.Cells(sheet3gyou, 1).Value = check
            End If
        Next
    Next
End Sub

sheet3gyouという変数を設け、最初は0、見つけたら1つ増やして、 Sheet3に切り替え、見つけた値をセルに代入する、という感じです。

プログラムを動かしてみると。。。

151.jpg

ん、いいんでないかい?(^^)

これで完成、、、と思ったんですけど。

今入ってるデータだったら問題ないんですけど、 Sheet1内、Sheet2内で重複しているデータがあった場合、例えばこんな感じ。

16.jpg

この状態で実行すると、

17.jpg

こんな感じ。「a」はいいとして、「b」「c」が2つ出てます。

「b」はSheet1に2つありますから、それぞれがSheet2の1つと一致します。

なので、2つ出ます。「c」はSheet1の1つがSheet2の2つと一致しますので、やはりこれも2つ出ます。

重複しているものは出ているので、これでいいっちゃいいんですけど、ここは、

18.jpg

こう出たほうがスマートですかね?(^^;)

さて、どうやろうかな。

Sheet2の中で重複している場合(この場合「c」)は、Sheet2を上から見ていくとき、 1つ目が見つかった段階で、もうその値を探すのを止めてしまえばよさそうです。

見つかった場合、forのループを抜け出してしまう感じですね。

Sub test()
    Dim i              As Integer
    Dim j              As Integer
    Dim check          As String
    Dim sheet1lastgyou As Integer
    Dim sheet2lastgyou As Integer
    Dim sheet3gyou     As Integer
    
    'Sheet1の最終行を求める
    Sheets("Sheet1").Select
    ActiveSheet.Range("A1").End(xlDown).Select
    sheet1lastgyou = ActiveCell.Row
    
    'Sheet2の最終行を求める
    Sheets("Sheet2").Select
    ActiveSheet.Range("A1").End(xlDown).Select
    sheet2lastgyou = ActiveCell.Row
    
    'Sheet3の行数を0にしておく
    sheet3gyou = 0
    
    'Sheet1を1行目から最終行まで
    For i = 1 To sheet1lastgyou
        
        'Sheet1を選択します
        Sheets("Sheet1").Select
        
        'Sheet1のi行目の値を取り出します
        check = ActiveSheet.Cells(i, 1).Value
        
        'Sheet2を1行目から最終行まで
        For j = 1 To sheet2lastgyou
            'Sheet2を選択します
            
            Sheets("Sheet2").Select
            'Sheet2のj行目の値とcheckの値が同じだったら
            
            If ActiveSheet.Cells(j, 1).Value = check Then
                
                'Sheet3に代入するセルの行数を1つ増やします。
                sheet3gyou = sheet3gyou + 1
                
                'Sheet3を選択します
                Sheets("Sheet3").Select
                
                'セルに見つけた値を代入します
                ActiveSheet.Cells(sheet3gyou, 1).Value = check
                
                '1つ目が見つかったので、ループから抜けます
                Exit For
            End If
        Next
    Next
End Sub

見つかった後、セルに代入した後でExit forでループを抜け出します。実行してみると、

19.jpg

ん、「c」は1つだけになりました(^^)。

後は、Sheet1内で重複していた場合ですね。

Sheet1を1行ずつ見ていって、これからチェックしようとする値(checkという変数に代入しています)が、それまで見てきた行の中にあるかどうかをチェックし、もしもあった場合、その行を飛ばす、というのでどうでしょうか。

これなら、Sheet1の3行目の「b」を見ているときは、すでに2行目に「b」がありますから、飛ばすことになります。

というわけで、プログラムにしてみます。

Sub test()
    Dim i              As Integer
    Dim j              As Integer
    Dim k              As Integer
    Dim atta           As Integer
    Dim check          As String
    Dim sheet1lastgyou As Integer
    Dim sheet2lastgyou As Integer
    Dim sheet3gyou     As Integer
    
    'Sheet1の最終行を求める
    Sheets("Sheet1").Select
    ActiveSheet.Range("A1").End(xlDown).Select
    sheet1lastgyou = ActiveCell.Row
    
    'Sheet2の最終行を求める
    Sheets("Sheet2").Select
    ActiveSheet.Range("A1").End(xlDown).Select
    sheet2lastgyou = ActiveCell.Row
    
    'Sheet3の行数を0にしておく
    sheet3gyou = 0
    
    'Sheet1を1行目から最終行まで
    For i = 1 To sheet1lastgyou
        
        'Sheet1を選択します
        Sheets("Sheet1").Select
        
        'Sheet1のi行目の値を取り出します
        check = ActiveSheet.Cells(i, 1).Value
        
        'attaという変数を0にします。
        atta = 0
        
        'もし、Sheet1の2行目以降を見ている場合
        If i >= 2 Then
            
            '今見ている行の前の行までに今回の値があるかどうかを探します
            
            For k = 1 To i - 1
                
                If ActiveSheet.Cells(k, 1).Value = check Then
                    atta = 1
                    Exit For
                End If
            
            
            Next
        End If
        
        'もし、atta=0ならば、Sheet2を探します。
        If atta = 0 Then
            
            'Sheet2を1行目から最終行まで
            For j = 1 To sheet2lastgyou
                
                'Sheet2を選択します
                Sheets("Sheet2").Select
                
                'Sheet2のj行目の値とcheckの値が同じだったら
                If ActiveSheet.Cells(j, 1).Value = check Then
                    
                    'Sheet3に代入するセルの行数を1つ増やします。
                    sheet3gyou = sheet3gyou + 1
                    
                    'Sheet3を選択します
                    Sheets("Sheet3").Select
                    
                    'セルに見つけた値を代入します
                    ActiveSheet.Cells(sheet3gyou, 1).Value = check
                    
                    '1つ目が見つかったので、ループから抜けます
                    Exit For
                
                End If
            
            Next
        End If
    Next
End Sub

新たに、attaとkという変数を作りました。

もし、Sheet1の2行目以降を探す場合、それ以前の行の値を For k=1 to i-1 ということで、1行目から、今探している行(i)の1つ前までループし、その行のセルの値が、checkの値と同じかどうかを調べ、同じだったら、attaという変数に1を入れます。

もし見つからなかったら、attaの変数は0のままですので、 attaが0だったら、今度はSheet2を調べる、という事になります。

プログラムを実行すると、、、

20.jpg

ん、いいんでないかい(^^)

いちおう、これで完成、でいいかな・・・?

こちらにアップしておきます→vbastudy_0006.xls

Leave a Reply

(required)

(required)

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

© 2011 simple blog いろいろ勉強中 Suffusion theme by Sayontan Sinha