由於資料僅有一張表(如:檔案連結中的工作表:「全部資料」),僅能以此作為查詢依據,至於其真實性這裡將不作考究,只針對需求來做說明。
需求內容如下:
- 以「姓名」選出相關的「地址」,該「地址」可能會出現於資料中其他行,且會是另一人的「姓名」。
- 再以另一人的「姓名」選出其他相關的「地址」,相同方式循環找,直到所有相關「姓名」與「地址」都不在新增為止。
程式運作流程:
- 檔案開啟時,觸發「Workbook_Open」事件對「鄉鎮市」進行過濾,過濾並移除重複數值,用以建立第一層資料清單。
- 當使用者對「鄉鎮市」切換時,觸發「Workbook_SheetChange」事件,在指定工作表與儲存格位置後,可針對「鄉鎮市」挑選出不重複的「姓名」作為清單。
- 當使用者對「姓名」切換,觸發「Workbook_SheetChange」事件,在「全部資料」進行篩選查詢。
- 選出來後再逐一以「地址」進行查詢其他相關「姓名」。
- 「姓名」選出後再以「姓名」查詢「地址」,如此循環直到不在出現新的「姓名」或「地址」為止。
在VBE的ThisWorkbook中貼上以下程式碼。
Private Sub Workbook_BeforeClose(Cancel As Boolean) Workbooks(1).Sheets(1).Cells.Clear Workbooks(1).Save End Sub Private Sub Workbook_Open() 第一層清單產生 End Sub Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range) If Sh.Name = "資料顯示" Then If Target.Address = "$A$1" Then 第二層清單產生 ElseIf Target.Address = "$B$1" Then If Len(Sh.Range(Target.Address)) Then 以姓名過濾出地址 Do 以地址選出親屬 Loop While 以親屬姓名選出地址 最後結果傳至第一張工作表 End If End If End If End Sub
在VBE添加Module1並貼上以下程式碼。
Sub 第一層清單產生() Dim listcount1 As Integer Workbooks(1).Sheets(3).Columns(1).Clear '進階過濾篩選出不重複的鄉鎮市 With Workbooks(1).Sheets(2) .Range("C:C").AdvancedFilter Action:=xlFilterCopy, CopyToRange:=Workbooks(1).Sheets(3).Range("A1"), Unique:=True End With '賦予資料區域名稱為list1,等於是名稱管理員的設定 With Workbooks(1).Sheets(3) .Range(Cells(2, "A").Address, .Cells(Rows.count, "A").End(xlUp).Address).Name = "list1" End With '設定"資料驗證"中的清單 With Workbooks(1).Sheets(1).Range("A1").Validation .Delete .Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, _ Operator:=xlBetween, Formula1:="=list1" End With End Sub Sub 第二層清單產生() Dim listcount1 As Integer Workbooks(1).Sheets(3).Columns(2).Clear 以鄉鎮市過濾出姓名 '進階過濾篩選出不重複的姓名 With Workbooks(1).Sheets(4) .Range("A:A").AdvancedFilter Action:=xlFilterCopy, CopyToRange:=Workbooks(1).Sheets(3).Range("B1"), Unique:=True .Cells.Clear End With '賦予資料區域名稱為list2,等於是名稱管理員的設定 With Workbooks(1).Sheets(3) .Range(Cells(2, "B").Address, .Cells(Rows.count, "B").End(xlUp).Address).Name = "list2" End With '設定"資料驗證"中的清單 With Workbooks(1).Sheets(1).Range("B1") .Clear With .Validation .Delete .Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, _ Operator:=xlBetween, Formula1:="=list2" End With End With End Sub Sub 以鄉鎮市過濾出姓名() Dim tmp, line Dim i As Integer, count As Integer With Workbooks(1).Sheets(2) With .UsedRange '鄉鎮市篩選 .AutoFilter Field:=.Cells(1, "C").column, Criteria1:="=" & Sheets(1).Cells(1, 1) '選出符合條件的資料 Set tmp = .Resize(.Rows.count - 1).SpecialCells(xlCellTypeVisible) count = 1 For Each line In tmp.Areas For i = 1 To line.Rows.count Sheets(4).Cells(count, 1).Value = line(i, 5).Value count = count + 1 Next Next End With '關閉篩選 .AutoFilterMode = False End With End Sub Sub 以姓名過濾出地址() Dim tmp, line Dim i As Integer, j As Integer, count As Integer, column As Integer Workbooks(1).Sheets(4).Cells.Clear With Workbooks(1).Sheets(2) column = .Cells(1, Columns.count).End(xlToLeft).column With .UsedRange '姓名篩選 .AutoFilter Field:=.Cells(1, "E").column, Criteria1:="=" & Sheets(1).Cells(1, 2) '選出符合條件的資料 Set tmp = .Resize(.Rows.count - 1).SpecialCells(xlCellTypeVisible) count = 1 For Each line In tmp.Areas For i = 1 To line.Rows.count For j = 1 To column Sheets(4).Cells(count, j).Value = line(i, j).Value Next '取得符合條件的資料所在列位置 Sheets(4).Cells(count, column + 1).Value = line.Rows.row() + i - 1 If line.Rows.row() = 1 And Sheets(4).Cells(count, column + 1) = 1 Then Sheets(4).Cells(count, column + 1) = "行號" End If count = count + 1 Next Next End With '關閉篩選 .AutoFilterMode = False End With End Sub Sub 以地址選出親屬() Dim tmp, line Dim i As Integer, j As Integer, k As Integer, count As Integer, column As Integer, row As Integer With Workbooks(1).Sheets(2) column = .Cells(1, Columns.count).End(xlToLeft).column With .UsedRange row = Sheets(4).Cells(Rows.count, 1).End(xlUp).row count = row + 1 For k = 2 To row '地址篩選 .AutoFilter Field:=.Cells(1, "G").column, Criteria1:="=" & Sheets(4).Cells(k, 7) '選出符合條件的資料 Set tmp = .Offset(1).Resize(.Rows.count - 1).SpecialCells(xlCellTypeVisible) For Each line In tmp.Areas For i = 1 To line.Rows.count For j = 1 To column Sheets(4).Cells(count, j).Value = line(i, j).Value Next '取得符合條件的資料所在列位置 Sheets(4).Cells(count, column + 1).Value = line.Rows.row() + i - 1 count = count + 1 Next Next Next End With '關閉篩選 .AutoFilterMode = False End With '針對重複資料進行移除 row = Workbooks(1).Sheets(4).Cells(Rows.count, 1).End(xlUp).row column = Workbooks(1).Sheets(4).Cells(1, Columns.count).End(xlToLeft).column ReDim col(0 To column - 1) For i = 0 To column - 1 col(i) = i + 1 Next Workbooks(1).Sheets(4).Range("A1:J" & row).RemoveDuplicates Columns:=(col), Header:=xlYes Workbooks(1).Sheets(3).Cells(1, 30) = Workbooks(1).Sheets(4).Cells(Rows.count, 1).End(xlUp).row End Sub Function 以親屬姓名選出地址() Dim tmp, line Dim i As Integer, j As Integer, k As Integer, count As Integer, column As Integer, row As Integer With Workbooks(1).Sheets(2) column = .Cells(1, Columns.count).End(xlToLeft).column With .UsedRange row = Sheets(4).Cells(Rows.count, 1).End(xlUp).row count = row + 1 For k = 2 To row '親屬姓名篩選 .AutoFilter Field:=.Cells(1, "E").column, Criteria1:="=" & Sheets(4).Cells(k, 5) '選出符合條件的資料 Set tmp = .Offset(1).Resize(.Rows.count - 1).SpecialCells(xlCellTypeVisible) For Each line In tmp.Areas For i = 1 To line.Rows.count For j = 1 To column Sheets(4).Cells(count, j).Value = line(i, j).Value Next '取得符合條件的資料所在列位置 Sheets(4).Cells(count, column + 1).Value = line.Rows.row() + i - 1 count = count + 1 Next Next Next End With '關閉篩選 .AutoFilterMode = False End With '針對重複資料進行移除 row = Workbooks(1).Sheets(4).Cells(Rows.count, 1).End(xlUp).row Workbooks(1).Sheets(4).Range("A1:J" & row).RemoveDuplicates Columns:=Array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10), Header:=xlYes 以親屬姓名選出地址 = False Workbooks(1).Sheets(3).Cells(1, 31) = Workbooks(1).Sheets(4).Cells(Rows.count, 1).End(xlUp).row If Workbooks(1).Sheets(3).Cells(1, 30) <> Workbooks(1).Sheets(3).Cells(1, 31) Then 以親屬姓名選出地址 = True End If End Function Sub 最後結果傳至第一張工作表() Dim row As Integer, column As Integer With Workbooks(1).Sheets(1) row = .Cells(Rows.count, 1).End(xlUp).row If row < 5 Then row = 5 .Rows("5:" & row).Clear End With With Workbooks(1).Sheets(4) row = .Cells(Rows.count, 1).End(xlUp).row column = .Cells(1, Columns.count).End(xlToLeft).column Workbooks(1).Sheets(1).Cells(5, 1).Resize(row, column).Value = .Cells(1, 1).Resize(row, column).Value End With End Sub
執行結果:
檔案連結。
沒有留言:
張貼留言