2016-01-27 69 views
0

使用Range.Find方法遍歷一個範圍中的每個值以查看它是否存在於另一個範圍中。問題在於兩個範圍的格式都不相同(但所有值都是表面上的日期),這導致了許多「錯誤否定」(即,值在它們應該是時不匹配)。是否有可能控制輸入和搜索範圍的數據類型,以便系統將蘋果與蘋果進行比較併成功識別匹配?VBA。查找,日期,序列號日期和數據類型屬性(.Text,.Value,.Value2)

下面是數據和代碼:

Sheet1 (custom format, "yyyy-mm-dd") 
A1 2016-01-01 
A2 2016-01-02 
A3 2016-01-03 
A4 2016-01-04 
A5 2016-01-05 

Sheet2 (text format) 
A1 2016-01-01 
A2 2016-01-03 
A3 2016-01-05 

Sheet3 (display as "yyyy-mm-dd") 
[NO DATA] 

Sheet4 (display as "yyyy-mm-dd") 
[NO DATA] 

代碼:

Sub FindTest() 
      Dim inputRange As Range 
      Dim searchRange As Range 
      Dim found As Range 
      Set inputRange = Worksheets(1).Cells(1, 1).Resize(7, 1) 
      Set searchRange = Worksheets(2).Cells(1, 1).Resize(5, 1) 
      For Each i In inputRange 
       Set found = searchRange.Find _ 
        (What:=i, _ 
        after:=Cells(1, 1), _ 
        LookIn:=xlValues, _ 
        LookAt:=xlWhole, _ 
        SearchOrder:=xlByRows, _ 
        SearchDirection:=xlNext, _ 
        MatchCase:=False, _ 
        SearchFormat:=False) 
       If Not (found Is Nothing) Then 
        Worksheets(3).Cells(i.Row, i.Column) = i 
       Else 
        Worksheets(4).Cells(i.Row, i.Column) = i 
       End If 
      Next i 
     End Sub 

對於這項工作,我認爲我需要inputRange和searchRange所有的值作爲被比較.Text,但我不確定到那裏。

+0

你有沒有考慮修復數據,以便蘋果蘋果和桔子不? – Jeeped

+0

而不是Searchrange.Find使用WHILE循環並逐個比較單元格,然後比較將相同的日期格式轉換爲日期格式,然後進行比較。我認爲你的問題將通過這個解決... –

+0

@Jeeped - 我們已經嘗試過這種方法,但一直未能弄清楚如何使用PowerQuery持續強制執行所需的格式。在生產中,結果是無論我們如何在PowerQuery中定義日期,生成的Excel表都無法反映這些格式,而VBA將數據作爲日期序列號讀取,這意味着它無法將其與相同日期相匹配格式爲yyyy-mm-dd。 –

回答

1

如果您需要將數據保留爲真正的日期和文本 - 看起來像日期那麼格式化他飛行時的真實日期值以查找「文本日期」內的匹配。

Sub FindTest() 
    Dim inputRange As Range, i As Range 
    Dim searchRange As Range, found As Range 

    Set inputRange = Worksheets(1).Cells(2, 1).Resize(99, 1) 
    Set searchRange = Worksheets(2).Columns(1) 

    For Each i In inputRange 
     If IsDate(i) Then      ' ▼ format into TXT here ▼ 
      Set found = searchRange.Find(What:=Format(i.Value2, "yyyy-mm-dd"), _ 
          after:=Cells(1), LookIn:=xlValues, LookAt:=xlWhole, _ 
          SearchOrder:=xlByRows, SearchDirection:=xlNext, _ 
          MatchCase:=False, SearchFormat:=False) 
      If Not (found Is Nothing) Then 
       With Worksheets(3) 
        .Cells(i.Row, i.Column) = i.Address(external:=True) 
        .Cells(i.Row, i.Column + 1) = i.Address(external:=True) 
       End With 
      Else 
       With Worksheets(4) 
        .Cells(i.Row, i.Column) = i.Address(external:=True) 
        .Cells(i.Row, i.Column + 1) = i.Address(external:=True) 
       End With 
      End If 
     End If 
    Next i 
End Sub 

或者,Range.Text property應提供相同的答案。應用Trim命令以確保inputRange日期未使用格式掩碼中的尾隨_)格式化。

 Set found = searchRange.Find(What:=Trim(i.Text), _ 
         after:=Cells(1), LookIn:=xlValues, LookAt:=xlWhole, _ 
         SearchOrder:=xlByRows, SearchDirection:=xlNext, _ 
         MatchCase:=False, SearchFormat:=False) 

附錄:

如果有領導或searchRange尾隨空格的可能性,然後更改您的搜索參數LookAt:=xlPart。雖然預先修復數據仍然是更好的選擇,但它會忽略可能干擾成功匹配的無關字符。

如果修復數據可以被認爲是一個選項,然後在文本值毯子Range.TextToColumns method用年月日xlColumnDataType將迅速轉換您yyyy-mm-dd「文本的日期」爲真正的日期。

With searchRange 
     .TextToColumns Destination: .Cells (1), DataType:=xlFixedWidth, _ 
         FieldInfo:=Array(0, 5) 
    End With 

這將刪除前/後多餘的字符,讓你與真正的日期列。

+0

感謝您的詳細回覆!對不起,我最初並不清楚。在生產中,這個日期將成爲唯一ID的一部分,所以我實際上希望它格式化爲文本而不是日期(我意識到searchRange已經在工作簿中被格式化爲文本,但我想以編程方式控制它因爲底層格式可能會改變)。所以我需要將inputRange和searchRange轉換爲(或看作)Text。如果我理解正確,上面的兩個解決方案將轉換inputRange,但不轉換searchRange。 –

+0

我試圖在下面使用TextToColumns,但它不成功。請參閱回答代碼... –

0

TextToColumn代碼(不成功)

Sub FindTest() 
Dim inputRange As Range 
Dim i As Range 
Dim searchRange As Range 
Dim found As Range 
Set inputRange = Worksheets(1).Cells(1, 1).Resize(7, 1) 
Set searchRange = Worksheets(2).Cells(1, 1).Resize(5, 1) 
searchRange.TextToColumns Destination:=Worksheets(2).Cells(1), DataType:=xlDelimited, FieldInfo:=Array(1, xlTextFormat) 
For Each i In inputRange 
    Set found = searchRange.Find _ 
     (What:=i, _ 
     after:=Cells(1, 1), _ 
     LookIn:=xlValues, _ 
     LookAt:=xlWhole, _ 
     SearchOrder:=xlByRows, _ 
     SearchDirection:=xlNext, _ 
     MatchCase:=False, _ 
     SearchFormat:=False) 
    If Not (found Is Nothing) Then 
     Worksheets(3).Cells(i.Row, i.Column) = i 
    Else 
     Worksheets(4).Cells(i.Row, i.Column) = i 
    End If 
Next i 

末次