在另一个工作表链接的单元格中查找值

时间:2018-04-05 09:38:57

标签: vba excel-vba excel-2016 excel

今天我的.Find功能出现了新问题。我正在尝试。通过一个工作表,其中包含从另一个工作表链接的单元格。 我有ws1,其中包含来自ws2的链接日期的标题行。举个例子: ws1 A1单元格公式为= ws2!$ A $ 1,ws1 B1公式为= ws2!$ A $ 2。 ws2在A列中包含日期。

我在ws1中使用.Find来查找用户表单(即ComboBox1.Value)上ComboBox1中显示的值。 ComboBox1源直接链接到ws2 A列,更新时的值更改为dd-mmm-yy格式。

以下是代码:

Private Sub TestSub()
Dim colRng As Range

With Worksheets("ws1").Range("A1:FZ200")
    Set colRng = .Find(CDate(ComboBox1.Value))
End With
MsgBox "colRng is: " + colRng.Address

End Sub

这给了我运行时错误91:对象或With Block变量未设置。在Debug上,colRng的值是Nothing而不是Range。

我唯一能想到的是链接的单元格正在弄乱格式,但我不知道如何解决这个问题。有什么想法吗?

更新:我在语句中测试了.Find函数,其中包含一个可以正常工作的字符串。

With Worksheets("ws1").Range("A1:FZ200")
    Set colRng = .Find(ComboBox1.Value)
End With
MsgBox "colRng is: " + colRng.Address

如果它是从另一张纸链接的,我不知道怎样去查找单元格中的值。有什么建议吗?

2 个答案:

答案 0 :(得分:1)

嗯,.Find()没找到任何东西,这就是原因。 你知道你在找什么吗?如果你写CDate(ComboBox1.Value)它会得到预期值吗?

一般情况下,为了避免在.Find()找不到任何内容时出现此错误,这就是解决方法:

If Not colRng Is Nothing Then
    MsgBox "colRng is: " + colRng.Address
End If

答案 1 :(得分:1)

所以日期在Excel中难以处理,因为它们可以被解释为整数或字符串(并使用不同的时区进行格式化)

为了便于修复,以下代码应允许取消注释一行以查找相应的日期或字符串

Private Sub TestSub()
    Dim colRng As Range

    With Worksheets("ws1")
        sFind = ComboBox1.Value
        'Set colRng = .Range("A1:FZ200").Find(CDate(sFind), LookIn:=xlValues)
        'Set colRng = .Range("A1:FZ200").Find(Format(CDate(sFind), "dd/mm/yyyy"), LookIn:=xlValues)
    End With
    If Not colRng Is Nothing Then Debug.Print "colRng is: " + colRng.Address

End Sub

作为更完整的答案,您可以使用以下通用FindAll函数...

Private Sub FindAllDates()
    Dim Rng1 As Range, Rng2 As Range, AllRng As Range, sFind As String

    With Worksheets("ws1")
        sFind = ComboBox1.Value
        Set Rng1 = FindAll(CDate(sFind), .Range("A1:FZ200"), LookIn:=xlValues)
        Set Rng2 = FindAll(Format(CDate(sFind), "dd/mm/yyyy"), .Range("A1:FZ200"), LookIn:=xlValues)
    End With
    Set AllRng = CombineRange(Rng1, Rng2)
    If Not AllRng Is Nothing Then Debug.Print "AllRng is: " + AllRng.Address

End Sub

Function CombineRange(R1 As Range, R2 As Range) As Range
    On Error Resume Next
    Set CombineRange = R1
    If Not R2 Is Nothing Then Set CombineRange = Application.Union(R1, R2)
    If CombineRange Is Nothing Then Set CombineRange = R2
End Function

Function FindAll(What, _
    Optional SearchWhat As Variant, _
    Optional LookIn, _
    Optional LookAt, _
    Optional SearchOrder, _
    Optional SearchDirection As XlSearchDirection = xlNext, _
    Optional MatchCase As Boolean = False, _
    Optional MatchByte, _
    Optional SearchFormat) As Range

    'LookIn can be xlValues or xlFormulas, _
     LookAt can be xlWhole or xlPart, _
     SearchOrder can be xlByRows or xlByColumns, _
     SearchDirection can be xlNext, xlPrevious, _
     MatchCase, MatchByte, and SearchFormat can be True or False. _
     Before using SearchFormat = True, specify the appropriate settings for the Application.FindFormat _
     object; e.g. Application.FindFormat.NumberFormat = "General;-General;""-"""

    Dim SrcRange As Range
    If IsMissing(SearchWhat) Then
        Set SrcRange = ActiveSheet.UsedRange
    ElseIf TypeOf SearchWhat Is Range Then
        Set SrcRange = IIf(SearchWhat.Cells.Count = 1, SearchWhat.Parent.UsedRange, SearchWhat)
    ElseIf TypeOf SearchWhat Is Worksheet Then
        Set SrcRange = SearchWhat.UsedRange
    Else: SrcRange = ActiveSheet.UsedRange
    End If
    If SrcRange Is Nothing Then Exit Function

    'get the first matching cell in the range first
    With SrcRange.Areas(SrcRange.Areas.Count)
        Dim FirstCell As Range: Set FirstCell = .Cells(.Cells.Count)
    End With

    Dim CurrRange As Range: Set CurrRange = SrcRange.Find(What:=What, After:=FirstCell, LookIn:=LookIn, LookAt:=LookAt, _
        SearchDirection:=SearchDirection, MatchCase:=MatchCase, MatchByte:=MatchByte, SearchFormat:=SearchFormat)

    If Not CurrRange Is Nothing Then
        Set FindAll = CurrRange
        Do
            Set CurrRange = SrcRange.Find(What:=What, After:=CurrRange, LookIn:=LookIn, LookAt:=LookAt, _
            SearchDirection:=SearchDirection, MatchCase:=MatchCase, MatchByte:=MatchByte, SearchFormat:=SearchFormat)
            If CurrRange Is Nothing Then Exit Do
            If Application.Intersect(FindAll, CurrRange) Is Nothing Then
                Set FindAll = Application.Union(FindAll, CurrRange)
            Else: Exit Do
            End If
        Loop
    End If
End Function