VBA - 使用搜索功能在两个日期之间设置范围

时间:2013-11-16 21:33:02

标签: excel vba excel-vba

我正在尝试让我的VBA代码在列中搜索用户输入的值(在表单上),并根据值设置范围。

我需要代码在列中向下扫描,直到找到值(这是一个日期),然后在列中向上扫描以获取范围的第二部分。我需要它是这样的,因为可能存在同一日期的多个实例,并且它们都需要被考虑。

我试过这个:

StartRange = ws.Cells.Find(What:=StartDate, SearchOrder:=xlRows, _
    SearchDirection:=xlNext, LookIn:=xlValues)

EndRange = ws.Cells.Find(What:=EndDate, SearchOrder:=xlRows, _
    SearchDirection:=xlPrevious, LookIn:=xlValues)

但它没有像我预期的那样工作,而且是错误的。 (编辑:已经定义了WS,所以我知道这不是问题)。我甚至不知道我是否正确地采取这种方式

我感到失败了:(

任何帮助将不胜感激,提前致谢!

编辑:

我还没有尝试任何建议,因为我现在离开了我的项目,但我觉得我需要澄清一些事情。

  1. 日期总是按时间顺序排列,我有一个脚本可以在表单激活时组织它们

  2. 我需要能够错误处理数据库中没有出现的日期,我还需要脚本能够“跳过”不存在的日期。即,1日1日,3日,3日,5日。如果我的开始和结束日期是第1和第5,整个示例将是范围。

  3. 感谢你们的帮助到目前为止,我很感激!

    EDIT2:

    我已经尝试了几个答案并将其添加到我的代码中,但现在它在Range_Global上失败了。

    Dim startrange, endrange, searchrange As Range
    LookUpColumn = 2
    
    With ws.Columns(LookUpColumn)
        Set startrange = .Find(What:=Me.R_Start.Value, _
          After:=ws.Cells(.Rows.count, LookUpColumn), _
          SearchOrder:=xlRows, _
          SearchDirection:=xlNext, LookIn:=xlValues)
    
        Set endrange = .Find(What:=Me.R_End.Value, _
          After:=ws.Cells(5, LookUpColumn), _
          SearchOrder:=xlRows, _
          SearchDirection:=xlPrevious, LookIn:=xlValues)
    
        searchrange = Range(startrange, endrange)
    
    MsgBox searchrange.Address
    End With
    

    有什么建议吗?

3 个答案:

答案 0 :(得分:2)

使用Find是执行此类操作的正确方法,您只需要了解一些细节。

  • 使用Set指定范围参考。例如Set StartRange = ...(并确保Dim StartRange as Range)。同上EndRangeSearchRange

  • 指定After单元格。请注意,默认情况下,这是搜索范围的左上角单元格,搜索在此单元格后开始。如果你的StartDate碰巧在单元格A1(和另一个单元格)中,那么保留默认将返回错误的结果

  • 将搜索范围限制为感兴趣的列。

  • Dim所有变量。每个变量都需要自己的As(并使用Option Explicit

最终结果

Dim startrange As Range, endrange As Range, searchrange As Range
Dim LookUpColumn as Long

LookUpColumn = 2
With ws.Columns(LookupColumn)
    ' Make sure lookup column data is type Date
    Set searchrange = .SpecialCells(xlCellTypeConstants)
    searchrange.Value = searchrange .Value
    Set searchrange = Nothing

    Set StartRange = .Find(What:=CDate(StartDate), _
      After:=.Cells(.Rows.Count, LookupColumn), _
      SearchOrder:=xlRows, _
      SearchDirection:=xlNext, LookIn:=xlValues)

    Set EndRange = .Find(What:=CDate(EndDate), _
      After:=.Cells(1, LookupColumn), _
      SearchOrder:=xlRows, _
      SearchDirection:=xlPrevious, LookIn:=xlValues)
End With

Set searchrange = Range(startrange, endrange)
MsgBox searchrange.Address

答案 1 :(得分:1)

让我们从这开始,看看需要微调的内容。 此代码将查找日期(基于输入),在列中查找该日期的位置。与“EndDate”相同,然后在2个位置之间的该列上创建一个范围

Sub ARange()
Dim Sh As Worksheet: Set Sh = Sheets("Sheet1")
Dim i, j As Integer

LookupColumn = "A" 'Define the LookupColum / If you find using column index to be simpler then you need to switch the search from (range) to (cells)
StartDate_Value = Sh.Range("B2").Value 'Use whatever you need to define the input values
EndDate_Value = Sh.Range("C2").Value 'Use whatever you need to define the input values

For i = 1 To 30000
    If Sh.Range(LookupColumn & i).Value = EndDate_Value Then EndDate_Row = i
Next i

For j = EndDate_Row To 1 Step -1
    If Sh.Range(LookupColumn & j).Value = StartDate_Value Then StartDate_Row = j
Next j

Dim MyDateRange As Range: Set MyDateRange = Sh.Range(LookupColumn & StartDate_Row & ":" & LookupColumn & EndDate_Row)
MsgBox "MyDateRange = " & LookupColumn & StartDate_Row & ":" & LookupColumn & EndDate_Row
End Sub

另一种方法应该意味着从下到上查找EndDate(如在Excel的列值中),从上到下查找StartDate。像这样:

For i = 30000 to 1 step -1
For j = 1 To 30000

第三个(魅力):从上到下为EndDate,从上到下为StartDate。像这样:

For i = 1 to 30000
For j = 1 To 30000

第四个(The One):

For i = 1 to 30000
For j = 30000 to 1 Step -1

在我的家用笔记本电脑上,对30.000个小区的搜索是即时的(低于1秒)。 试一试,根据反馈,我们可以对其进行微调。

另一方面,我可能会看到你的问题,因为看起来要选择不是顶部/底部位置之间的所有值,但任何具有2个输入值之间的日期值的单元格永远不会选择值的排列列表(列单元格)。即如果StartDate = 1.Jan.2013和EndDate = 3.Jan.2013。代码应从30.000列表中选取1,2和3,永远不要指出这3个日期的位置(事实上可能会发现数千次)。如果这是真的,那么解决方案可能比上面的解决方案更简单。

答案 2 :(得分:1)

由于几个原因,我不喜欢这个日期搜索的概念。

  • 假设日期总是按顺序
  • 假设两个日期都存在于列表中

虽然在这种情况下这些可能是有效的假设,但我确信可能存在这种情况可能并非如此......

我不知道这样做的最佳方法,但另一个需要考虑的方法是使用自动过滤器

类似的东西:

 Sub FindDateRange()

Dim sht As Worksheet
Dim column As Long
Set sht = Sheet1

Dim rng As Range, inclusiveRange As Range
Dim startDate As Long, endDate As Long

column = 2

On Error GoTo Err

startDate = DateValue("02/10/2012")
endDate = DateValue("05/10/2012")

Application.Calculation = xlCalculationManual
Application.ScreenUpdating = False


    sht.Cells(1, column).AutoFilter Field:=column, Criteria1:=">=" & startDate, Operator:=xlAnd _
            , Criteria2:="<=" & endDate


    Set rng = sht.Range(sht.Cells(2, column), sht.Cells(sht.Cells(sht.Rows.Count, column).End(xlUp).Row, column)).SpecialCells(xlCellTypeVisible)

    sht.AutoFilterMode = False

    If rng.Address = sht.Cells(1, column).Address Then



        MsgBox Format(startDate, "dd-mmm-yyyy") & " - " & Format(endDate, "dd-mmm-yyyy") _
        & vbCrLf & vbCrLf & "No instances of the date range exist"

    Else

    Set inclusiveRange = sht.Range(rng.Cells(1, 1), rng.Cells(rng.Count, 1))

        MsgBox Format(startDate, "dd-mmm-yyyy") & " - " & Format(endDate, "dd-mmm-yyyy") _
        & vbCrLf & vbCrLf & "the range is " & rng.Address & vbCrLf & vbCrLf & _
        "inclusive range is " & inclusiveRange.Address
    End If





continue:

    Application.ScreenUpdating = True
    Application.Calculation = xlCalculationAutomatic

Exit Sub

Err:
    MsgBox Err.Description
    GoTo continue


End Sub

Example2

Example1

Example3