我已经编写了一个代码摘录,用于测试概念验证的大型程序。 (因此少量代码。)主代码背后的想法是让用户使用带有复选框的自定义用户窗体生成数组,然后在数组中搜索所有提及的“1”,即当复选框有被选中。然后使用数组的行号加载一系列额外的UserForms,基于哪些复选框被选中。我想有更简单的方法可以做到这一点,但这是我选择的方法,我对VBA的编码经验相当有限!
我附上了生成的数组示例。
当我运行代码时,除了大小写之外,它就像inteneded一样工作 细胞(1,2)= 1
任何人都可以发现为什么会这样,我现在一直在努力解决这个问题。
Sub Array_Finder()
Dim StartFinder As String
Dim StartFinderZero As String
Dim StartFinderCheck As String
i = 4 : j = 1
StartFinderZero = 0 : StartFinderCheck = i + 2
For StartFinderTest = 1 To i + 1
StartFinder = StartFinderZero + 1
If StartFinderCheck > StartFinder Then
StartFinderZero = Range(Cells(StartFinder, 2), Cells(i + 1, 2)).Find _
(What:="1", after:=Cells(StartFinder, 2), searchdirection:=xlNext).Row
Cells(StartFinderTest, 3) = StartFinderZero
Else
MsgBox ("here")
Exit For
End If
Next StartFinderTest
End Sub
答案 0 :(得分:3)
使用您的代码:
Sub ArrayFinder()
Dim StartFinder As Long
Dim StartFinderZero As String
Dim StartFinderCheck As String
i = 4: j = 1
StartFinderZero = 0: StartFinderCheck = i + 2
For StartFinderTest = 1 To i + 1
StartFinder = StartFinderZero + 1
If StartFinderCheck > StartFinder Then
With Range(Cells(StartFinder, 2), Cells(i + 1, 2))
Debug.Print "row" & vbTab & .Cells(.Cells.Count).Row
Debug.Print "address" & vbTab & .Address
Debug.Print "after"; vbTab & .Cells(.Cells.Count).Address
StartFinderZero = .Find(1, after:=.Cells(.Cells.Count)).Row
End With
Cells(StartFinderTest, 3) = StartFinderZero
Else
Debug.Print "here"
Exit For
End If
Next StartFinderTest
End Sub
这是你在即时窗口得到的:
row 5
address $B$1:$B$5
after $B$5
row 5
address $B$2:$B$5
after $B$5
诀窍是以下(来自MSDN的After参数):
您希望搜索开始的单元格。这对应于从用户界面进行搜索时活动单元的位置。请注意,After必须是范围内的单个单元格。请记住,搜索在此单元格之后开始; 指定的单元格不会被搜索,直到该方法回绕到此单元格。如果不指定此参数,则搜索范围左上角的单元格后开始搜索。
因此,您可以将最后一个单元格作为开头。它知道它应该从之后开始。因此,它理论上没有更好的事情可做,只是从范围的开始开始。 After
参数的想法是设置要检查的最后一个值。 因此,如果我们只有一个值,它总是正确返回 ,无论After
参数如何。如果有多个值,则返回它找到的第一个值。
因此,在上面的代码中,由于 After 的使用,.Find()
按以下顺序搜索单元格:
B1> B2> B3> B4> B5
如果没有 After ,则序列如下:
B2> B3> B4> B5> B1
为了更好地说明,假设您有两个不同的范围:
使用左边的那个,如果你搜索1
的行,即使没有选择after参数,你也总是没问题,使用这个代码:
Sub TestMe()
Dim myR As Range
Dim myS As Range
Set myS = Range("B1:B5") 'change the range
With myS
Set myR = .Find(1)
Debug.Print myR.Row
Set myR = .Find(1, after:=.Cells(.Cells.Count))
Debug.Print myR.Row
End With
End Sub
右边的范围是棘手的,因为它也有1
两次。因此,after
是必须的,以便从第一个单元格中获取值。如果您尝试它,您将在即时窗口中显示2
和1
。
而且这就是为什么在某些时候我决定使用一个慢速方法,它只是在范围内循环并检查值,而不是内置的.Find()
GitHub link to LastThings
答案 1 :(得分:1)
我假设一切都发生在一张纸上。它适用于您提供的数据。
Sub MyAnswer()
Dim lRow As Long ' Number of rows (or last row)
Dim rngCheckBoxes As Range ' Range of values
Dim vArr()
' Calculate last row
lRow = ActiveSheet.Range("A" & ActiveSheet.Rows.Count).End(xlUp).Row
' Define range of checkboxes' numbers
Set rngCheckBoxes = ActiveSheet.Range("A1","A" & lRow)
' Replace all zeroes with empty string
rngCheckBoxes.Offset(0,1).Replace "0", "", xlWhole
' Put all values from defined range into array
' where according values from column next to it aren't blank
vArr = rngCheckBoxes.Offset(0,1).SpecialCells(xlCellTypeConstants).Offset(0,-1).Value
' Insert array values into column "C"
ActiveSheet.Range("C1").Resize(Ubound(vArr),1).Value = vArr
End Sub