|
面白そうなので作って見た物の、余り自信が有りません
再帰呼び出しを使っているので、Shee1の6000行の時にスタックオーバーに成るかも?
また、処理は何度もSheet1のデータを行ったり来たりするので遅いと思います
なお、コードは処理確認用(削除行の最終列に「削除」の文字を出力するだけ)と
実処理用(実際に行削除を行うもの)の2つUpします
Option Explicit
Public Sub Sample_1()
' 処理確認用
'◆Listのデータ列数(A列〜B列)
Const clngColumns As Long = 2
'◆Listの中の親と成る列位置(基準列からの列Offset:1列目)
Const clngKey1 As Long = 0
'◆Listの中の子と成る列位置(基準列からの列Offset:2列目)
Const clngKey2 As Long = 1
Dim i As Long
Dim j As Long
Dim lngRows As Long
Dim rngList As Range
Dim rngDelete As Range
Dim vntList As Variant
Dim vntDelete As Variant
Dim vntFlags() As Variant
Dim strProm As String
'◆Listの先頭セル位置を基準とする(先頭列の列見出しのセル位置)
Set rngList = Worksheets("Sheet1").Cells(1, "A")
'◆結果出力の先頭セル位置を基準とする(先頭列の列見出しのセル位置)
Set rngDelete = Worksheets("Sheet2").Cells(1, "A")
With rngDelete
'行数の取得
lngRows = .Offset(Rows.Count - .Row).End(xlUp).Row - .Row
If lngRows <= 0 Then
strProm = "データが有りません"
GoTo Wayout
End If
'列データを配列に取得
vntDelete = .Offset(1).Resize(lngRows + 1).Value
End With
With rngList
'行数の取得
lngRows = .Offset(Rows.Count - .Row, clngKey1).End(xlUp).Row - .Row
If lngRows <= 0 Then
strProm = "データが有りません"
GoTo Wayout
End If
'親子データを格納する配列を確保
ReDim vntList(0 To 1)
'親列データを配列に取得
vntList(0) = .Offset(1, clngKey1).Resize(lngRows + 1).Value
'子列データを配列に取得
vntList(1) = .Offset(1, clngKey2).Resize(lngRows + 1).Value
'削除フラグを格納する配列を確保
ReDim vntFlags(1 To lngRows, 1 To 1)
End With
'削除行の抽出(Sheet2先頭の「BBB」だけ)
DataDeleteF vntDelete(1, 1), vntList, 1, vntFlags()
'削除行の抽出(Sheet2のA列全て)
' For i = 1 To UBound(vntDelete, 1) - 1
' DataDeleteF vntDelete(i, 1), vntList, 1, vntFlags()
' Next i
'画面更新を停止
' Application.ScreenUpdating = False
'フラグを出力
rngList.Offset(1, clngColumns).Resize(lngRows).Value = vntFlags
strProm = "処理が完了しました"
Wayout:
'画面更新を再開
Application.ScreenUpdating = True
Set rngList = Nothing
Set rngDelete = Nothing
MsgBox strProm, vbInformation
End Sub
Private Sub DataDeleteF(vntKey As Variant, _
vntList As Variant, _
lngRow As Long, _
vntFlags() As Variant)
Do Until vntList(0)(lngRow, 1) = ""
If vntKey = vntList(0)(lngRow, 1) Then
vntFlags(lngRow, 1) = "削除"
DataDeleteF vntList(1)(lngRow, 1), vntList, lngRow + 1, vntFlags()
End If
lngRow = lngRow + 1
Loop
End Sub
Public Sub Sample_2()
' データ削除
'◆Listのデータ列数(A列〜B列)
Const clngColumns As Long = 2
'◆Listの中の親と成る列位置(基準列からの列Offset:1列目)
Const clngKey1 As Long = 0
'◆Listの中の子と成る列位置(基準列からの列Offset:2列目)
Const clngKey2 As Long = 1
Dim i As Long
Dim j As Long
Dim lngRows As Long
Dim rngList As Range
Dim rngDelete As Range
Dim vntList As Variant
Dim vntDelete As Variant
Dim lngFlags() As Long
Dim lngCount As Long
Dim strProm As String
'◆Listの先頭セル位置を基準とする(先頭列の列見出しのセル位置)
Set rngList = Worksheets("Sheet1").Cells(1, "A")
'◆結果出力の先頭セル位置を基準とする(先頭列の列見出しのセル位置)
Set rngDelete = Worksheets("Sheet2").Cells(1, "A")
With rngDelete
lngRows = .Offset(Rows.Count - .Row).End(xlUp).Row - .Row
If lngRows <= 0 Then
strProm = "データが有りません"
GoTo Wayout
End If
vntDelete = .Offset(1).Resize(lngRows + 1).Value
End With
With rngList
lngRows = .Offset(Rows.Count - .Row, clngKey1).End(xlUp).Row - .Row
If lngRows <= 0 Then
strProm = "データが有りません"
GoTo Wayout
End If
ReDim vntList(0 To 1)
vntList(0) = .Offset(1, clngKey1).Resize(lngRows + 1).Value
vntList(1) = .Offset(1, clngKey2).Resize(lngRows + 1).Value
ReDim lngFlags(1 To lngRows, 1 To 1)
End With
'削除行の抽出(Sheet2先頭の「BBB」だけ)
' DataDelete vntDelete(1, 1), vntList, 1, lngFlags(), lngCount
'削除行の抽出(Sheet2のA列全て)
For i = 1 To UBound(vntDelete, 1) - 1
DataDelete vntDelete(i, 1), vntList, 1, lngFlags(), lngCount
Next i
Application.ScreenUpdating = False
With rngList
'削除行が有るなら
If lngCount > 0 Then
'フラグを出力
.Offset(1, clngColumns).Resize(lngRows).Value = lngFlags
'フラグをKeyとして整列(削除行を下に集める)
DataSort .Offset(1).Resize(lngRows, clngColumns + 1), .Offset(, clngColumns)
'フラグが立っている行を削除
.Offset(lngRows - lngCount + 1).Resize(lngCount, _
clngColumns + 1).Delete Shift:=xlShiftUp
'フラグ列を削除
.Offset(, clngColumns).EntireColumn.Delete
End If
End With
strProm = "処理が完了しました"
Wayout:
'画面更新を再開
Application.ScreenUpdating = True
Set rngList = Nothing
Set rngDelete = Nothing
MsgBox strProm, vbInformation
End Sub
Private Sub DataDelete(vntKey As Variant, _
vntList As Variant, _
lngRow As Long, _
lngFlags() As Long, _
lngCount As Long)
Do Until vntList(0)(lngRow, 1) = ""
If vntKey = vntList(0)(lngRow, 1) Then
lngFlags(lngRow, 1) = 1
lngCount = lngCount + 1
DataDelete vntList(1)(lngRow, 1), vntList, lngRow + 1, lngFlags(), lngCount
End If
lngRow = lngRow + 1
Loop
End Sub
Private Sub DataSort(rngScope As Range, _
rngKey As Range, _
Optional lngSortOrder As Long = xlAscending, _
Optional lngOrientation As Long = xlTopToBottom)
rngScope.Sort _
Key1:=rngKey, Order1:=lngSortOrder, _
Header:=xlNo, OrderCustom:=1, MatchCase:=False, _
Orientation:=lngOrientation, SortMethod:=xlStroke
End Sub
|
|