我正在尝试让我的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日1日,3日,3日,5日。如果我的开始和结束日期是第1和第5,整个示例将是范围。
感谢你们的帮助到目前为止,我很感激!
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
有什么建议吗?
答案 0 :(得分:2)
使用Find
是执行此类操作的正确方法,您只需要了解一些细节。
使用Set
指定范围参考。例如Set StartRange = ...
(并确保Dim StartRange as Range
)。同上EndRange
和SearchRange
指定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