Board logo

標題: [發問] 請問各位前輩關於Find 與比對Range 問題 [打印本頁]

作者: ii31sakura    時間: 2014-6-23 18:13     標題: 請問各位前輩關於Find 與比對Range 問題

不好意思、請問前輩一下~小弟有一份資料情況如下:
1.比對data   2.來源data  3.總整理

資料為使用vba 去尋找"比對data"最後一筆的("A~D")的資料,
去核對sheet"來源data"中("A~D")的資料如果有完全相符的就從sheet"來源data"中將該列的資料copy到sheet"總整理"。
因小弟使用Find、但卻卡在這次需尋找是一個區塊而非單一字串或儲存格內容,
所以請前輩能不能指導一下小弟接下來該如何改寫?

感謝~

[attach]18543[/attach]
作者: GBKEE    時間: 2014-6-23 20:32

回復 1# ii31sakura
試試看
  1. Sub Ex()
  2.     Dim Ar(), i As Integer, S As String
  3.     With Sheets("比對data").Range("A" & Sheets("比對data").Rows.Count).End(xlUp).Resize(, 4)
  4.         S = Join(Application.Transpose(Application.Transpose(.Value)), "")
  5.         '"比對data"最後一筆的("A~D")的資料
  6.     End With
  7.     With Sheets("總整理")
  8.         .Cells.Clear
  9.         .Range("A1").Resize(, 7) = Sheets("來源data").Range("A1").Resize(, 7).Value     '表頭
  10.         Ar = Sheets("來源data").Range("A1:D5").Value  'sheet"來源data"中("A~D")
  11.         For i = 1 To UBound(Ar)
  12.             If S = Join(Application.Index(Ar, i), "") Then
  13.                 .Range("A" & .Rows.Count).End(xlUp).Offset(1).Resize(, 7) = _
  14.                     Sheets("來源data").Cells(i, "A").Resize(, 7).Value
  15.             End If
  16.         Next
  17.     End With
  18. End Sub
複製代碼

作者: ii31sakura    時間: 2014-6-24 10:00

回復 2# GBKEE

感謝GBKEE前輩~不好意思再請問一下、小弟如果想知道完全相符的(來源data)是第幾欄位,
如果直接輸入(msgbox s) 則會顯示{("A~D")的資料}內容、如果輸入(msgbox s.address 或 msgbox s row)都顯示"不正確的定位項,
請問小弟該輸入些什麼呢?
作者: GBKEE    時間: 2014-6-24 10:47

回復 3# ii31sakura
  1. Sub Ex()
  2.     Dim Ar(), i As Integer, S As String, Rng As Range, ss
  3.     With Sheets("比對data").Range("A" & Sheets("比對data").Rows.Count).End(xlUp).Resize(, 4)
  4.         S = Join(Application.Transpose(Application.Transpose(.Value)), "")
  5.         '"比對data"最後一筆的("A~D")的資料
  6.     End With
  7.     With Sheets("總整理")
  8.         .Cells.Clear
  9.         .Range("A1").Resize(, 7) = Sheets("來源data").Range("A1").Resize(, 7).Value     '表頭
  10.         Ar = Sheets("來源data").Range("A1:D5").Value  'sheet"來源data"中("A~D")
  11.         For i = 1 To UBound(Ar)
  12.             If S = Join(Application.Index(Ar, i), "") Then
  13.                 Set Rng = Sheets("來源data").Cells(i, "A").Resize(, 7)
  14.                 MsgBox "在 第" & i & " 列  找到 " & Join(Application.Transpose(Application.Transpose(Rng.Value)), ",")
  15.                 .Range("A" & .Rows.Count).End(xlUp).Offset(1).Resize(, 7) = Rng.Value
  16.             End If
  17.         Next
  18.     End With
  19. End Sub
複製代碼

作者: ii31sakura    時間: 2014-6-27 17:08

回復 4# GBKEE

不好意思、GBKEE前輩可否再請指導一下,
如果來源data資料列位超過比對data列位、請問可從哪邊修改_可比對來源data到最後呢?

註:小弟有將附件內容修改一下(比對data只到第5列、來源data到第5列之後就無法進行比對動作)
   
可否請麻煩一下~
[attach]18576[/attach]
作者: GBKEE    時間: 2014-6-27 20:02

回復 6# ii31sakura
修改為 R => 由A欄最底部往上到有資料儲存格的列號
  1. 'Ar = Sheets("來源data").Range("A1:D5").Value  'sheet"來源data"中("A~D")
  2.         With Sheets("來源data")
  3.             R = .Cells(.Rows.Count, "a").End(xlUp).Row
  4.             Ar = .Range("A1:D" & R).Value 'sheet"來源data"中("A~D")
  5.         End With
複製代碼

作者: ii31sakura    時間: 2014-8-16 14:45

本帖最後由 ii31sakura 於 2014-8-16 14:51 編輯

回復 6# GBKEE

不好意思、GBKEE前輩請問一下因小弟使用範例(ex1)可以正確找到想要的答案(比對data最後A&B 兩個儲存格在於來源data屬於哪個row),
但因小弟將範例用於data筆數破萬時發現執行較久,
故想請問是不是有像(ex2)的Find方式可以尋找正確的答案row在何處呢或是請問(ex1)可指點如何修改呢??

註:
因ex2中小弟使用 Union將來源data需比較的兩欄放一起想用Find找兩個條件,但實際上還是無法實現我想要的答案(如ex1所能正確的找出第幾列)、
能不能懇請幫忙一下~
   
[attach]18929[/attach]

Sub ex2()
    Dim range1 As Range, range2 As Range, range3 As Range, range4 As Range
    Dim allrange As Range, allrange1 As Range, c As Integer

   
b = Worksheets("比對data").[b65536].End(3).Row
c = Worksheets("來源data").[b65536].End(3).Row
   
Set range1 = Sheets("來源data").Range("A" & 2 & ":" & "A" & c)
Set range2 = Sheets("來源data").Range("b" & 2 & ":" & "b" & c)
Set allrange = Union(range1, range2)



          '此區塊為先找row
         Set findvalue = allrange.Find(What:=Worksheets("比對data").Cells(b, 2))  '←此種只能找尋單一儲存格,請問是否能實現下一段備註情況,可以找兩條件呢?
'Set findvalue = allrange.Find(What:=Worksheets("比對data").Cells(b, 1) & Worksheets("比對data").Cells(b, 2)) '問題點(有方法可正確使兩個儲存格的條件都可找到嗎?此段請問能否指點小弟該如何修改呢?)
          MsgBox findvalue.Row


    Set range1 = Nothing: Set range2 = Nothing: Set allrange = Nothing: Set findvalue = Nothing



End Sub
作者: GBKEE    時間: 2014-8-16 16:38

回復 7# ii31sakura
試試看
  1. Option Explicit
  2. Sub Ex2()
  3.     Dim Rng(1 To 2) As Range, Rng2_Address As String
  4.     Set Rng(1) = Worksheets("比對data").Range("A2")                    '比對data的第一筆資料(日期)
  5.     Do While Rng(1) <> ""                                              '執行到條件不成立
  6.         With Sheets("來源data").Range("A:A")                           '範圍:這工作表的A欄
  7.             Set Rng(2) = .Find(Rng(1), AFTER:=.Cells(1), LookIn:=xlFormulas) '搜尋日期:要用公式LookIn:=xlFormulas
  8.             Do While Not Rng(2) Is Nothing                              '執行到條件不成立
  9.                 If Rng2_Address = "" Then Rng2_Address = Rng(2).Address '記錄第一次找到的位置
  10.                 If Rng(1).Cells(1, 2) = Rng(2).Cells(1, 2) Then     '
  11.                     Rng(1).Cells(1, 3) = Rng(2).Cells(1, 3)             '比對的第二欄=來源data的第二欄
  12.                     Exit Do
  13.                 End If
  14.                 Set Rng(2) = .FindNext(Rng(2))                          '繼續往下搜尋
  15.                 If Rng2_Address = Rng(2).Address Then                   '回到第一次找到的位置
  16.                     Exit Do                                             '離開迴圈
  17.                 End If
  18.             Loop
  19.             Rng2_Address = ""
  20.             Set Rng(1) = Rng(1).Offset(1)                               '比對data的下一筆資料(日期)
  21.         End With
  22.     Loop
  23. End Sub
複製代碼

作者: ii31sakura    時間: 2014-8-16 23:04

回復 8# GBKEE

非常感謝GBKEE前輩~真是佛心來的,前輩還幫忙每段用註解、真感謝~
作者: ii31sakura    時間: 2014-8-18 15:25

回復 8# GBKEE

抱歉、GBKEE前輩…能否再請指導附檔中如果比對條件能否從兩個比對條件變更為三個比對條件呢?
因小弟另一個檔案發現兩個比對條件可能會碰到重覆性情況、如果使用三個比對條件就不會有重覆情況,
能否請問可於何處進行修改呢?
不好意思了...


    [attach]18953[/attach]

Sub Ex3()
    Dim Rng(1 To 2) As Range, Rng2_Address As String
    Set Rng(1) = Worksheets("比對data").Range("A2")                    '比對data的第一筆資料(日期)
    Do While Rng(1) <> ""                                              '執行到條件不成立
        With Sheets("來源data").Range("A:A")                           '範圍:這工作表的A欄
            Set Rng(2) = .Find(Rng(1), AFTER:=.Cells(1), LookIn:=xlFormulas) '搜尋日期:要用公式LookIn:=xlFormulas
            Do While Not Rng(2) Is Nothing                              '執行到條件不成立
                If Rng2_Address = "" Then Rng2_Address = Rng(2).Address '記錄第一次找到的位置
                If Rng(1).Cells(1, 2) = Rng(2).Cells(1, 2) Then     '
'                    Rng(1).Cells(1, 3) = Rng(2).Cells(1, 3)             '比對的第二欄=來源data的第二欄
                    
                    Rng(1).Cells(1, 4) = Rng(2).Row '此段為找該資料的row
                    
                    Exit Do
                End If
                Set Rng(2) = .FindNext(Rng(2))                          '繼續往下搜尋
                If Rng2_Address = Rng(2).Address Then                   '回到第一次找到的位置
                    Exit Do                                             '離開迴圈
                End If
            Loop
            Rng2_Address = ""
            Set Rng(1) = Rng(1).Offset(1)                               '比對data的下一筆資料(日期)
        End With
    Loop
End Sub
作者: GBKEE    時間: 2014-8-18 19:49

回復 10# ii31sakura
  1. Option Explicit
  2. Sub Ex()
  3.     Dim d As Object, Rng As Range, S As String
  4.     Set d = CreateObject("scripting.dictionary")
  5.     Set Rng = Sheets("比對data").Range("A2")
  6.     Do While Rng <> ""
  7.         d(Rng & Rng.Cells(1, 2) & Rng.Cells(1, 3)) = ""
  8.         Set Rng = Rng.Cells(2, 1)
  9.     Loop
  10.     Set Rng = Sheets("來源data").Range("A2")
  11.     Do While Rng <> ""
  12.         If d.EXISTS(Rng & Rng.Cells(1, 2) & Rng.Cells(1, 3)) Then
  13.             If d.EXISTS("比對到") Then
  14.                 Set d("比對到") = Union(Rng.Resize(, 3), d("比對到"))
  15.             Else
  16.                 Set d("比對到") = Rng.Resize(, 3)
  17.             End If
  18.         
  19.             S = IIf(S <> "", S & vbLf, "") & Rng.Address(0, 0) & " 找到 " & Rng & "-" & Rng.Cells(1, 2) & "-" & Rng.Cells(1, 3)
  20.         End If
  21.         Set Rng = Rng.Cells(2, 1)
  22.     Loop
  23.     If S <> "" Then
  24.         d("比對到").Parent.Activate
  25.          d("比對到").Select
  26.         MsgBox "來源data " & vbLf & S
  27.     End If
  28. End Sub
  29. Sub Ex3()
  30.     Dim Rng(1 To 2) As Range, Rng2_Address As String
  31.     Set Rng(1) = Worksheets("比對data").Range("A2")                    '比對data的第一筆資料(日期)
  32.     Sheets("來源data").UsedRange.Offset(1).Interior.ColorIndex = xlNone
  33.     Do While Rng(1) <> ""                                              '執行到條件不成立
  34.         With Sheets("來源data").Range("A:A")                           '範圍:這工作表的A欄
  35.             Set Rng(2) = .Find(Rng(1), AFTER:=.Cells(1), LookIn:=xlFormulas) '搜尋日期:要用公式LookIn:=xlFormulas
  36.             Do While Not Rng(2) Is Nothing                              '執行到條件不成立
  37.                 If Rng2_Address = "" Then Rng2_Address = Rng(2).Address '記錄第一次找到的位置
  38.                 If Rng(1).Cells(1, 2) = Rng(2).Cells(1, 2) And Rng(1).Cells(1, 3) = Rng(2).Cells(1, 3) Then      '
  39. '                     Rng(1).Cells(1, 3) = Rng(2).Cells(1, 3)             '比對的第二欄=來源data的第二欄
  40.                     
  41.                     Rng(1).Cells(1, 4) = Rng(2).Row '此段為找該資料的row
  42.                     Rng(2).Resize(, 3).Interior.Color = vbYellow
  43.                     
  44.                     Exit Do
  45.                 End If
  46.                 Set Rng(2) = .FindNext(Rng(2))                          '繼續往下搜尋
  47.                 If Rng2_Address = Rng(2).Address Then                   '回到第一次找到的位置
  48.                     Exit Do                                             '離開迴圈
  49.                 End If
  50.             Loop
  51.             Rng2_Address = ""
  52.             Set Rng(1) = Rng(1).Offset(1)                               '比對data的下一筆資料(日期)
  53.         End With
  54.     Loop
  55. End Sub
複製代碼

作者: ii31sakura    時間: 2014-8-18 21:54

回復 11# GBKEE

感謝GBKEE前輩指導兩個方法、讓小弟可以有多一層空間變化,
不好意思如果小弟套用的來源端屬於不同excel、
故使用以下方式進行設定、但似乎漏了哪個環節而導致無法執行,
因嘗試許久無法正解、請問能不能再請幫忙看一下呢?

[attach]18955[/attach]

程式碼:
Sub Ex3()
    Dim Rng(1 To 2) As Range, Rng2_Address As String
     Dim wb(1 To 2) As Workbook
    Dim myApp As New Application
   
   
     Set wb(1) = ThisWorkbook '使用於sheet(比對data)
    Set wb(2) = myApp.Workbooks.Open(Worksheets("路徑區").Cells(2, 3) & "\" & Worksheets("路徑區").Cells(2, 2))  '使用於另一個excel sheet(來源data)
   
    Set Rng(1) = wb(1).Worksheets("比對data").Range("A2")                    '比對data的第一筆資料(日期)
    Do While Rng(1) <> ""                                              '執行到條件不成立
        With wb(2).Sheets("來源data").Range("A:A")                           '範圍:這工作表的A欄
            Set Rng(2) = .Find(Rng(1), AFTER:=.Cells(1), LookIn:=xlFormulas) '搜尋日期:要用公式LookIn:=xlFormulas
            Do While Not Rng(2) Is Nothing                              '執行到條件不成立
                If Rng2_Address = "" Then Rng2_Address = Rng(2).Address '記錄第一次找到的位置
                If Rng(1).Cells(1, 2) = Rng(2).Cells(1, 2) Then     '
'                    Rng(1).Cells(1, 3) = Rng(2).Cells(1, 3)             '比對的第二欄=來源data的第二欄
                    
                    Rng(1).Cells(1, 3) = Rng(2).Row '此段為找該資料的row
                    
                    Exit Do
                End If
                Set Rng(2) = .FindNext(Rng(2))                          '繼續往下搜尋
                If Rng2_Address = Rng(2).Address Then                   '回到第一次找到的位置
                    Exit Do                                             '離開迴圈
                End If
            Loop
            Rng2_Address = ""
            Set Rng(1) = Rng(1).Offset(1)                               '比對data的下一筆資料(日期)
        End With
    Loop
   
   
       wb(2).Close False
        
        
        Set wb(1) = Nothing
        Set wb(2) = Nothing
        Set Rng(1) = Nothing: Set Rng(2) = Nothing
'        Set findvalue = Nothing
End Sub
作者: GBKEE    時間: 2014-8-19 10:41

回復 12# ii31sakura
  1. Dim myApp As New Application
  2. With wb(2).Sheets("來源data").Range("A:A")                           '範圍:這工作表的A欄
  3. Set Rng(2) = .Find(Rng(1).Value, AFTER:=.Cells(1), LookIn:=xlFormulas) '搜尋日期:要用公式LookIn:=xlFormulas
複製代碼
Rng(2) is nothing 無法突破

試試不新開 Excel 應用程式
  1. Sub Ex3()
  2.     Dim Rng(1 To 3) As Range, Rng2_Address As String
  3.     Dim wb(1 To 2) As Workbook
  4.    ' Dim myApp As New Application  '為何要新開 Excel
  5.     Set wb(1) = ThisWorkbook '使用於sheet(比對data)
  6.     'Set wb(2) = myApp.Workbooks.Open(Worksheets("路徑區").Cells(2, 3) & "\" & Worksheets("路徑區").Cells(2, 2))  '使用於另一個excel sheet(來源data)
  7.     Set wb(2) = Workbooks.Open(Worksheets("路徑區").Cells(2, 3) & "\" & Worksheets("路徑區").Cells(2, 2))  '使用於另一個excel sheet(來源data)
  8.     Set Rng(1) = wb(1).Worksheets("比對data").Range("A2")                    '比對data的第一筆資料(日期)
  9.     Do While Rng(1) <> ""                                              '執行到條件不成立
  10.         With wb(2).Sheets("來源data").Range("A:A")                           '範圍:這工作表的A欄
  11.             Set Rng(2) = .Find(Rng(1).Value, AFTER:=.Cells(1), LookIn:=xlFormulas) '搜尋日期:要用公式LookIn:=xlFormulas
  12.             Do While Not Rng(2) Is Nothing                              '執行到條件不成立
  13.                 If Rng2_Address = "" Then Rng2_Address = Rng(2).Address '記錄第一次找到的位置
  14.                 If Rng(1).Cells(1, 2) = Rng(2).Cells(1, 2) Then     '
  15. '                    Rng(1).Cells(1, 3) = Rng(2).Cells(1, 3)             '比對的第二欄=來源data的第二欄
  16.                   
  17.                    ' Rng(1).Cells(1, 3) = Rng(2).Row '此段為找該資料的row
  18.                    '******************
  19.                     If Rng(3) Is Nothing Then
  20.                         Set Rng(3) = Rng(2).Resize(, 3)
  21.                     Else
  22.                     
  23.                         Set Rng(3) = Union(Rng(3), Rng(2).Resize(, 3))
  24.                     End If
  25.                     '*********************
  26.                     Exit Do
  27.                 End If
  28.                 Set Rng(2) = .FindNext(Rng(2))                          '繼續往下搜尋
  29.                 If Rng2_Address = Rng(2).Address Then                   '回到第一次找到的位置
  30.                     Exit Do                                             '離開迴圈
  31.                 End If
  32.             Loop
  33.             Rng2_Address = ""
  34.             Set Rng(1) = Rng(1).Offset(1)                               '比對data的下一筆資料(日期)
  35.         End With
  36.     Loop
  37.     If Not Rng(3) Is Nothing Then
  38.          With wb(1).Worksheets("總整理")
  39.             .UsedRange.Offset(1) = ""
  40.             Rng(3).Copy .Range("A2")
  41.         End With
  42.     End If
  43.        wb(2).Close False
  44.        Set wb(1) = Nothing
  45.         Set wb(2) = Nothing
  46.         Set Rng(1) = Nothing
  47.         Set Rng(2) = Nothing

  48. End Sub
複製代碼

作者: ii31sakura    時間: 2014-8-19 12:13

回復 13# GBKEE


    感謝GBKEE前輩指導、因為小弟的資料來源大多為區網上的共用excel data,
    會使用例子1因擔心可能來源data已先被其它人開啟會有開啟警告問題,
    經前輩提醒後、小弟實際去測試使用例子2、即使有人開起來源data也似乎不影響程式的運行,
    在此謝謝前輩的指導囉~

例子1:' Dim myApp As New Application  '為何要新開 Excel
例子2:Set wb(2) = Workbooks.Open
作者: ii31sakura    時間: 2014-8-19 17:05

回復 13# GBKEE

不好意思 GBKEE前輩,因小弟工作關係需套用於別處、請問如果來源資料wb(2)開起時出現如下圖的( 無法更新的連結),
請問該如何將來源資料的自動更新關閉呢?

註:小弟爬文嘗試使用語句2來關閉來源資料警告、但可能卡在語句1已經先開啟,所以總是出現錯誤情況。

語句1: Set wb(2) = Workbooks.Open(Worksheets("路徑區").Cells(2, 3) & "\" & Worksheets("路徑區").Cells(2, 2))  '使用於另一個excel sheet(來源data)
語句2:Workbooks.Open Filename:="D:\週別資料\wk1432\find 比對問題\find 與比對Range 問題3 - 來源data.xlsm" ,UpdateLinks:=0

[attach]18962[/attach]
作者: ii31sakura    時間: 2014-8-19 19:11

回復 13# GBKEE

GBKEE前輩~不好意思…後來小弟嘗試在開啟檔案前加上"Application.DisplayAlerts = False '關閉所有EXCEL程序系統提示"之後就可以正常值行了,
真是不好意思這麼麻煩您。
   

感謝前輩前幾段的指導~




歡迎光臨 麻辣家族討論版版 (http://forum.twbts.com/)