Excel VBA質問箱 IV

当質問箱は、有志のボランティア精神のおかげで成り立っています。
問題が解決したら、必ずお礼をしましょうね。
本サイトの基本方針をまとめました。こちら をご一読ください。

投稿種別の選択が必要です。ご注意ください。
迷惑投稿防止のため、URLの入力を制限しています。ご了承ください。


23616 / 76738 ←次へ | 前へ→

【58488】Re:重複チェック
回答  Hirofumi  - 08/10/27(月) 22:18 -

引用なし
パスワード
   「ファイル1」、「ファイル2」が既に開かれて居る物とします
データが大きいので上手く行かないかも

Option Explicit
Option Compare Text

Public Sub DataMatch()

  '「ファイル1」のデータ列数(A列〜E列)
  Const clngColumns1 As Long = 5
  '「ファイル2」のデータ列数(A列〜E列)
  Const clngColumns2 As Long = 5
  '「一致」を入れる列位置(基準位置からの列Offset:E列)
  Const clngStamp As Long = 4
  
  Dim rngList1 As Range
  Dim vntList1 As Variant
  Dim lngRows1 As Long
  Dim lngComp1 As Long
  Dim vntKeys1 As Variant
  Dim vntData1 As Variant
  Dim rngList2 As Range
  Dim vntList2 As Variant
  Dim lngRows2 As Long
  Dim lngComp2 As Long
  Dim vntKeys2 As Variant
  Dim vntData2 As Variant
  Dim lngMatch As Long
  
  Dim strProm As String

  '「ファイル1」データシートのA1を基準とします
  Set rngList1 = Workbooks("ファイル1.xls").Worksheets("Sheet1").Cells(1, "A")
  
  '「ファイル2」データシートのA1を基準とする
  Set rngList2 = Workbooks("ファイル2.xls").Worksheets("Sheet1").Cells(1, "A")
    
  '「ファイル1」の比較列の列挙(基準セル位置からの列Offsetを列挙)
  'A列=0、C列=2、E列=4
  vntKeys1 = Array(0, 1, 2, 3)
  '「ファイル2」の比較列の列挙(基準セル位置からの列Offsetを列挙)
  'A列=0、C列=2、E列=4
  vntKeys2 = Array(0, 1, 2, 3)
  
  '「ファイル1」の比較データを保持する配列を確保
  ReDim vntList1(0 To UBound(vntKeys1))
  '「ファイル2」の比較データを保持する配列を確保
  ReDim vntList2(0 To UBound(vntKeys1))
  
  '画面更新を停止
  Application.ScreenUpdating = False
  
  '「ファイル1」の基準に就いて
  If Not GetBasicData(rngList1, lngRows1, _
        clngColumns1, vntKeys1, vntList1) Then
    strProm = rngList1.Parent.Name & "にデータが有りません"
    GoTo Wayout
  End If
  
  '「ファイル2」基準に就いて
  If Not GetBasicData(rngList2, lngRows2, _
        clngColumns2, vntKeys2, vntList2) Then
    strProm = rngList2.Parent.Name & "にデータが有りません"
    GoTo Wayout
  End If
  
  '「ファイル1」のシートの比較位置
  lngComp1 = 1
  '「ファイル2」のシートの比較位置
  lngComp2 = 1
  '「ファイル1」のシート若しくは、「ファイル2」のシートが最終行に達するまで繰り返し
  Do Until lngComp1 > lngRows1 Or lngComp2 > lngRows2
    '各列のデータを比較
    lngMatch = IsSame(vntList1, lngComp1, vntList2, lngComp2)
    '比較結果に就いて
    Select Case lngMatch
      Case Is = 0 'Matchiした場合
        With rngList1.Offset(lngComp1)
          .Offset(, clngStamp).Value = "一致"
          .Resize(, clngColumns1).Interior.Color = vbGreen
        End With
        With rngList2.Offset(lngComp2)
          .Offset(, clngStamp).Value = "一致"
          .Resize(, clngColumns2).Interior.Color = vbGreen
        End With
        '「ファイル1」「ファイル2」のシートの比較位置を更新
        lngComp1 = lngComp1 + 1
        lngComp2 = lngComp2 + 1
      Case Is = -1 '「ファイル1」の固有値の場合
        '「ファイル1」のシートの比較位置を更新
        lngComp1 = lngComp1 + 1
      Case Is = 1 '「ファイル2」の固有値の場合
        '「ファイル2」のシートの比較位置を更新
        lngComp2 = lngComp2 + 1
    End Select
  Loop
  
  '「ファイル1」のシートの順位を復帰
  DataRestore rngList1, lngRows1, clngColumns1
  
  '「ファイル2」のシートの順位を復帰
  DataRestore rngList2, lngRows2, clngColumns2

  strProm = "処理が完了しました"
  
Wayout:
  
  '画面更新を再開
  Application.ScreenUpdating = True
  
  Set rngList1 = Nothing
  Set rngList2 = Nothing
  
  MsgBox strProm, vbInformation
  
End Sub

Private Function GetBasicData(rngList As Range, _
                lngRows As Long, _
                lngColumns As Long, _
                vntKeys As Variant, _
                vntData As Variant) As Boolean

  Dim i As Long
  Dim lngNumb() As Long
  
  '基準に就いて
  With rngList
    '行数を取得
    lngRows = .Offset(Rows.Count - .Row, _
            vntKeys(0)).End(xlUp).Row - .Row
    'データが無ければFunctionを抜ける(戻り値=False)
    If lngRows <= 0 Then
      Exit Function
    End If
    '復帰用整列Keyを作成
    ReDim lngNumb(1 To lngRows, 1 To 1)
    For i = 1 To lngRows
      lngNumb(i, 1) = i
    Next i
    '復帰用Keyの出力列を挿入
    .Offset(1, lngColumns).EntireColumn.Insert
    '復帰用Keyの出力
    .Offset(1, lngColumns).Resize(lngRows).Value = lngNumb
    'データをvntKeys1列で整列
    For i = UBound(vntKeys) To 0 Step -1
      DataSort .Offset(1).Resize(lngRows, _
          lngColumns + 1), .Offset(1, vntKeys(i))
    Next i
    '比較用配列にデータを取得
    For i = 0 To UBound(vntKeys)
      vntData(i) = .Offset(1, vntKeys(i)) _
                .Resize(lngRows + 1).Value
    Next i
  End With
  
  GetBasicData = True

End Function

Private Sub DataRestore(rngList As Range, _
            lngRows As Long, _
            lngColumns As Long)

  With rngList
    '元データ順位を復帰
    DataSort .Offset(1).Resize(lngRows, _
          lngColumns + 1), .Offset(1, lngColumns)
    '復帰用Key列を削除
    .Offset(1, lngColumns).EntireColumn.Delete
  End With

End Sub

Private Sub DataSort(rngScope As Range, _
          rngKey As Range, _
          Optional lngOrientation As Long = xlTopToBottom)

  rngScope.Sort _
      Key1:=rngKey, Order1:=xlAscending, _
      Header:=xlNo, OrderCustom:=1, MatchCase:=False, _
      Orientation:=lngOrientation, SortMethod:=xlStroke

End Sub

Private Function IsSame(vntKeys1 As Variant, lngPos1 As Long, _
            vntKeys2 As Variant, lngPos2 As Long) As Long

'  データの大小比較

  Dim i As Long
  Dim lngMax As Long
  
  '比較位置がDataEndを超えた場合
  If lngPos1 > UBound(vntKeys1(0), 1) - 1 Then
    IsSame = 1
    Exit Function
  End If
  If lngPos2 > UBound(vntKeys2(0), 1) - 1 Then
    IsSame = -1
    Exit Function
  End If
    
  '1行の最大比較回数を取得(実際は0から始まる為、回数としては+1と成る)
  lngMax = UBound(vntKeys1, 1)
  
  '1行のKeyを先頭から比較
  For i = 0 To lngMax
    'もし、Keyが不一致なら
    If vntKeys1(i)(lngPos1, 1) <> vntKeys2(i)(lngPos2, 1) Then
      'Forを抜ける
      Exit For
    End If
  Next i
  
  'Keyが全て一致した場合(Forが全て回り終った場合、iはlngMax+1と成る)
  If i > lngMax Then
    '戻り値の値として、「等しい」を返す
    IsSame = 0
  Else
    'vntKeys1の値が、vntKeys2の値因り小さい場合
    If vntKeys1(i)(lngPos1, 1) < vntKeys2(i)(lngPos2, 1) Then
      '戻り値の値として、「小さい」を返す
      IsSame = -1
    Else
      '戻り値の値として、「大きい」を返す
      IsSame = 1
    End If
  End If
  
End Function
1 hits

【58473】重複チェック 初心者 08/10/27(月) 16:45 質問
【58475】Re:重複チェック こぎつね 08/10/27(月) 16:59 発言
【58493】Re:重複チェック こぎつね 08/10/28(火) 6:45 発言
【58488】Re:重複チェック Hirofumi 08/10/27(月) 22:18 回答

23616 / 76738 ←次へ | 前へ→
ページ:  ┃  記事番号:
2610219
(SS)C-BOARD v3.8 is Free