• 締切済み

ExcelVBAで重複するデータを表示するには?

VBAで重複するデータを検索し,一致するデータがある場合は, その隣のセルを別シートにて横方向に表示させたいと思っています。 どのようにしたら,良ろしいでしょうか? 具体的には,下記のSheet1 のデータを元に,VBAでSheet2を作成したいと考えています。 <<Sheet1>> 社名   品名 -----+------+ A社     PC A社   プリンタ B社    モデム B社     PC A社    スキャナ C社     PC <<Sheet2>> 社名     品名1     品名2    品名3 -----+------+--------+--------+ A社     PC    プリンタ    スキャナ B社    モデム    PC C社      PC 関連して・・・  ・Sheet2の社名は重複表示させない  ・品名1,品名2,品名3の順番は,Sheet1にて1行目から検索してヒットする順番で表示  ・重複するデータがない場合(C社),そのまま社名と品名をSheet2に表示 以上,よろしくお願い致します。

みんなの回答

  • 30246kiku
  • ベストアンサー率73% (370/504)
回答No.4

Excel の関数等不慣れなので、そういう人が考えたら・・・の例になるか?も 重複排除・・・ Dictionary を使ってしまいます。 今回の場合、社名がキーで品名が内容 社名は出現順、品名も出現順(ただし、重複する品名は覚えない) 以下の関数を標準モジュールに記述しておきます。 Public Sub CngShowPtn(rng As Range, toRng As Range)   Dim dic As Object   Dim v As Variant, vr As Variant   Dim bNxt As Boolean   Dim i As Long, iv As Long, ivmax As Long   Set dic = CreateObject("Scripting.Dictionary")   With rng     i = 1     While (.Offset(i) <> "")       bNxt = True       v = dic.Item(.Offset(i).Value)       If (Not IsArray(v)) Then         ReDim v(0)       Else         For Each vr In v           If (vr = .Offset(i, 1).Value) Then             bNxt = False             Exit For           End If         Next         If (bNxt) Then ReDim Preserve v(UBound(v) + 1)       End If       If (bNxt) Then         v(UBound(v)) = .Offset(i, 1).Value         dic.Item(.Offset(i).Value) = v       End If       i = i + 1     Wend   End With   If (dic.Count > 0) Then     With toRng       i = 1       ivmax = 0       For Each v In dic.Keys         vr = dic.Item(v)         iv = UBound(vr) + 1         If (iv > ivmax) Then ivmax = iv         .Offset(i) = v         .Offset(i, 1).Resize(, iv) = vr         i = i + 1       Next       .Offset(0) = rng       For i = 1 To ivmax         .Offset(0, i) = rng.Offset(0, 1) & i       Next     End With   End If   Set dic = Nothing End Sub 使い方は、どこの表を、そして結果をどこに表示する を Range で指定します。 以下を実行してみた結果は、添付図のようになります。 Public Sub test()   Call CngShowPtn(Range("A1"), Range("D2"))   Call CngShowPtn(Range("A9"), Range("D10")) End Sub また、シートを修飾して指定したりします。 例)   Call CngShowPtn(Worksheets("Sheet1").Range("A1") _             , Worksheets("Sheet2").Range("A1"))

  • mt2008
  • ベストアンサー率52% (885/1701)
回答No.3

ANo.2です。 画像をせっかく作ったのに添付し忘れていました。

  • mt2008
  • ベストアンサー率52% (885/1701)
回答No.2

簡単なものを作ってみました。 該当社名が一番最初に登場する行の右に品名を追加していき、最後に社名登場が2番目以降の不要な行を削除して形を整えています。 Sub Sample()   Dim nMax, nMatch, nCol, sString, i   'Sheet1からSheet2にコピー   Sheets("Sheet1").Cells.Copy   Sheets("Sheet2").Range("A1").Select   ActiveSheet.Paste   nMax = Cells(Rows.Count, 1).End(xlUp).Row   For i = 2 To nMax 'データがあるのは2行目から     nMatch = WorksheetFunction.Match(Cells(i, 1), Range("A:A"), 0)     If nMatch <> i Then       '品名を右に表示       sString = sString & i & ":" & i & "," '不要行削除用       nCol = Cells(nMatch, 1).End(xlToRight).Column       Cells(nMatch, nCol + 1) = Cells(i, 2)     End If   Next i   '不要な行の削除   sString = Left(sString, Len(sString) - 1)   Range(sString).Delete Shift:=xlUp End Sub

  • cj_mover
  • ベストアンサー率76% (292/381)
回答No.1

こんにちは。 技術的に簡易なものを選んで書いてみました。 VBAに慣れたら、配列とか外部オブジェクトとか使いたくなると思いますが、 そこまで望んでいるようには見受けられなかったので、易しい方法にします。 具体的なご要望あれば、一応お応えするつもりです。 指定が漏れている点、都合上、すべて可変にして書いています。 以下こちらで仮に設定したもの。  社名は、A列にある  nKeyCol = 1  品名は、B列にある  nField2Col = nKeyCol + 1  統合するデータの元の列は(B列に始まり)B列で終る  nFieldsEndCol = nField2Col + 0  レコードの先頭行は3行め  nTopRow = 3  Sheet2 のフィールド名を設定する記述は省きました。 Sub Re7799914cc()   Dim vTemp  As Variant   Dim wshtP  As Worksheet   Dim flgA() As Boolean   Dim nKeyCol     As Long   Dim nField2Col   As Long   Dim nFieldsEndCol  As Long   Dim nTopRow     As Long   Dim nBottomRow   As Long   Dim nC As Long   Dim nR As Long   Dim i  As Long   Dim j  As Long   Dim k  As Long   Set wshtP = Sheets("Sheet2") '    ◆指定   nKeyCol = 1 '            ◆指定   nField2Col = nKeyCol + 1 ' 2 '    ◆指定   nFieldsEndCol = nField2Col + 0 ' 2 ' ◆指定   With Sheets("Sheet1") '       ◆指定     nTopRow = 3 '          ◆指定     nBottomRow = .Cells(Rows.Count, nKeyCol).End(xlUp).Row     ReDim flgA(nTopRow To nBottomRow) As Boolean     nR = nTopRow - 1     For i = nTopRow To nBottomRow       If Not flgA(i) Then         nR = nR + 1         vTemp = .Cells(i, nKeyCol).Value         wshtP.Cells(nR, nKeyCol).Value = vTemp         nC = nField2Col - 1         For k = nField2Col To nFieldsEndCol           nC = nC + 1           wshtP.Cells(nR, nC).Value = .Cells(i, k).Value         Next k         For j = i + 1 To nBottomRow           If Not flgA(j) Then             If .Cells(j, nKeyCol).Value = vTemp Then               flgA(j) = True               For k = nField2Col To nFieldsEndCol                 nC = nC + 1                 wshtP.Cells(nR, nC).Value = .Cells(j, k).Value               Next k             End If           End If         Next j       End If     Next i   End With   Set wshtP = Nothing   Erase flgA End Sub

関連するQ&A

専門家に質問してみよう