条件付きで重複行を処理したい場合はDictionaryオブジェクトの使用をお勧めします。
まずはプログラムソースから
'=====プログラムここから=====
Public Sub DoSyuukei()
Dim objDicNameList As Object
Dim NowReadRow As Long, MaxReadRow As Long
Dim NowReadCol As Long, MaxReadCol As Long
Dim NowIndex As Long, MaxIndex As Long
Dim NowWriteRow As Long
Dim objOutputRange As Range
Dim objSrcSheet As Worksheet
Dim varRangeWriteData() As Variant
Dim varResultArray As Variant
Dim strTemp As String
'=====設定部分=====
'元のデータを読み込みたいシートを指定
Set objSrcSheet = ThisWorkbook.Worksheets("Sheet1")
'結果を出力する部分の左上を指定
Set objOutputRange = ThisWorkbook.Worksheets("Sheet2").Range("A1")
'=====プログラム本体=====
'今回のミソ、Dictionaryオブジェクトの宣言
Set objDicNameList = CreateObject("Scripting.Dictionary")
'念のため全消去(なくてもOK)
objDicNameList.RemoveAll
'最終行を取得
MaxReadRow = objSrcSheet.Cells(objSrcSheet.Rows.Count, 1).End(xlUp).Row
'2行目から順に内容を解析していく(1行目はタイトルだから行わない)
For NowReadRow = 2 To MaxReadRow
'重複をチェックするのは顧客名と製品名の2個なので、この2個をタブ文字でつないだ文字列で重複チェックを行う
strTemp = objSrcSheet.Cells(NowReadRow, 2).Value & vbTab & objSrcSheet.Cells(NowReadRow, 3).Value
'この作成した文字がすでに出てきたかをチェックする
If objDicNameList.Exists(strTemp) = True Then
'登録されている場合は、登録されているデータの日付を読みだしてチェックする
'同じ日付である場合は下にある方が優先(「>=」を「>」にすると上にある方が優先になります)
If objSrcSheet.Cells(NowReadRow, 1).Value >= objDicNameList.Item(strTemp)(0) Then
'今読んでいるデータの方が新しい場合のみデータを再登録する(さらに重複回数を+1する)
objDicNameList.Item(strTemp) = Array(objSrcSheet.Cells(NowReadRow, 1).Value, NowReadRow, objDicNameList.Item(strTemp)(2) + 1)
Else
'データが新しくない場合は重複回数を+1するのみ
objDicNameList.Item(strTemp) = Array(objDicNameList.Item(strTemp)(0), objDicNameList.Item(strTemp)(1), objDicNameList.Item(strTemp)(2) + 1)
End If
Else
'登録されてない場合
'登録されていない場合は新規に登録する (日付,データのあるExcelの行番号,重複回数)の3個のデータを格納する
objDicNameList.Add strTemp, Array(objSrcSheet.Cells(NowReadRow, 1).Value, NowReadRow, 0)
End If
Next
'調査結果に従って結果を作成する
MaxIndex = objDicNameList.Count '何種類データがあったかを取得
'元のデータは何列データがあるかを取得( =3 などのように手で指定してもOK)
MaxReadCol = objSrcSheet.Cells(1, objSrcSheet.Columns.Count).End(xlToLeft).Column
'結果を入れる用の作業用データ領域を作成(こうすることで高速化が可能)
'見出し行のため1行多く設定する。更に重複であることを記入する場所のため、列も1列多く宣言する
ReDim varRangeWriteData(1 To MaxIndex + 1, 1 To MaxReadCol + 1)
'タイトル行を複写
For NowReadCol = 1 To MaxReadCol
varRangeWriteData(1, NowReadCol) = objSrcSheet.Cells(1, NowReadCol).Value
Next
varRangeWriteData(1, MaxReadCol + 1) = "重複回数" '重複回数の列タイトルを作成
'集計した結果を変数に吐き出しする
varResultArray = objDicNameList.Items
'objdicNameListの中に記録した行のデータを元にセルのデータを作成していく
NowWriteRow = 2 '1行目は見出し行なので2行目から開始
For NowIndex = 1 To MaxIndex
'元シートから読み込むべき行番号を取り出す
NowReadRow = varResultArray(NowIndex - 1)(1)
'読み出すべき行番号を元にその場所のデータを複写する
For NowReadCol = 1 To MaxReadCol
varRangeWriteData(NowWriteRow, NowReadCol) = objSrcSheet.Cells(NowReadRow, NowReadCol).Value
Next
'重複データであった場合は重複回数を書きだす
If varResultArray(NowIndex - 1)(2) > 0 Then
varRangeWriteData(NowWriteRow, MaxReadCol + 1) = varResultArray(NowIndex - 1)(2)
End If
'書きだす場所を次の行に変更
NowWriteRow = NowWriteRow + 1
Next
'作成したデータを貼り付けるのにどのくらいの大きさのセル範囲が必要かを計算して指定する
With objOutputRange.Worksheet.Range(objOutputRange, objOutputRange.Offset(UBound(varRangeWriteData, 1) - 1, UBound(varRangeWriteData, 2) - 1))
'作成したデータをExcelに貼り付け
.Value = varRangeWriteData
'.Sort "顧客名", , "製品名", , , , , xlYes '結果をソートしたければコメント解除して編集してください。左は顧客と製品名でソート
End With
'出したものはお片づけ
Set objOutputRange = Nothing
Set objDicNameList = Nothing
Set objSrcSheet = Nothing
End Sub
'=====プログラムここまで=====
Dictionaryオブジェクトを用いることにより、Exists(調べたい文字)とするだけで過去にその文字を登録したことがあるかを一発で調べることができます。詳しく知りたい場合は、[vba dictionary]さらに原理を知りたい場合は[連想配列]のあたりで検索をするといいでしょう。参考になるURLを3つほど紹介しておきます。
http://www.eurus.dti.ne.jp/~yoneyama/Excel/vba/vba_dictionary.html
http://officetanaka.net/excel/vba/tips/tips80.htm
http://www.php-labo.net/tutorial/php/hash.html (言語がVBでなくPHPだが、絵の雰囲気で解説するので良ければ参考に)
さらにもう1個、これは説明しているサイトが少ないですが、Dictionaryオブジェクトは格納できるのは値1個だけではなく、配列をそのまま格納することができてしまいます。Array(○○,△△)のように。それを用いて最新の日付はいつとか何回重複したかなどを実現しています。
文字数制限の関係で詳しく解説出来なかったですが、今後の参考とステップアップの糧になれば幸いです。
お礼
誠にありがとうございました。 一言、完璧!!でした。 本当にありがとうございます。 検証するのに時間がかかり、 お礼のメールが遅れてしまい、申し訳ありませんでした。 でも、Dictionaryオブジェクトは難しいですね。 本当にこれだけ丁寧に解説頂いてやっと 利用できたという感じです。 これからもすこしづつ頑張っていきたいと思いますので、 機会がありましたら、またお助け下さい。 宜しくお願い致します。