我有一个函数,可以在其中指定所需的字段和标题行号,然后返回该列。例如。 =findField("Region",1)
将返回包含标题“ Region”的列号。在我遇到标题行中包含重复名称的报告之前,此方法一直有效。例如。而不是第一个和姓氏,在两个字段中都将使用“名称”,因此我需要像第二个事件中的=findField("Name",1,2)
中那样指定我想要的事件。我想出了一个解决方案,但有2个问题。首先是,如果该字段在第一列中,它将无法正常工作。例如。如果列A和列B具有“名称”,那么=findField("Name",1,1)
将返回第二个字段而不是第一个字段,而=findField("Name",1,2)
将环绕并返回第一个字段,这不是我想要的。第二个问题是,它包裹了我不希望完全不做的地方。我想到的是:
Function findField2(fieldName As String, Optional rowStart As Long = 0, Optional occurrence As Long = 1)
Dim Found As Range, lastRow As Long, count As Integer, myCol As Long
If rowStart = 0 Then rowStart = getHeaderRow()
myCol = 1
For count = 1 To occurrence
Set Found = Rows(rowStart).Find(what:=fieldName, LookIn:=xlValues, lookat:=xlWhole, After:=Cells(rowStart, myCol))
If Found Is Nothing Then
MsgBox "Error: Can't find '" & fieldName & "' in row " & rowStart
Exit Function
Else
myCol = Found.Column
End If
Next count
lastRow = Cells(Rows.count, Found.Column).End(xlUp).Row
findField2 = Found.Column
要允许该字段位于A列中,我需要做什么?为myCol输入0无效。最初的查找功能基于https://www.mrexcel.com/forum/excel-questions/629346-vba-finding-text-row-1-return-column.html,我正在对其进行调整以满足自己的需求。
谢谢, 本
答案 0 :(得分:1)
有些不使用Find()
的东西仍然可以满足您的目标:
Function findField2(fieldName As String, Optional rowStart As Long = 0, _
Optional occurrence As Long = 1)
Dim a, rw As Range, m
If rowStart = 0 Then rowStart = getHeaderRow()
With ActiveSheet 'might be better to pass the sheet as a parameter
Set rw = Application.Intersect(.Rows(rowStart), .UsedRange)
a = .Evaluate("=IF(" & rw.Address & "=""" & fieldName & _
""",COLUMN(" & rw.Address & "),FALSE)")
End With
m = Application.Small(a, occurrence) 'find the n'th match (will return an error if none)
If IsError(m) Then MsgBox "No occurrence #" & occurrence & " of '" & _
fieldName & "' on row# " & rowStart, vbExclamation
findField2 = IIf(IsError(m), 0, m)
End Function
Sub Tester()
Debug.Print findField2("A", 5, 40)
End Sub
答案 1 :(得分:0)
此处没有对象引用,即,所有内容都引用了ActiveSheet
中的ActiveWorkbook
。
通过默认,查找方法从下一个单元格开始搜索(6. SearchDirection xlNext
或{{1} })中提供的After参数(2. After )的单元格范围参数,例如,如果您按行使用单元格1
(5. SearchOrder { 1}}或A1
),搜索将从xlByRows
开始,一直进行到最后一列,然后回绕并最后继续1
。因此,必须使用该行的最后单元格以第一个单元格B1
开始搜索。
仅当出现次数大于1时,才用A1
语句解决环绕问题。如果未发现任何出现,则返回A1
。
找到的单元格(If
)的列号将传递到变量(0
),并且每次出现该值时,都将相互检查它们。现在,如果变量等于列号,则函数返回intCol
,表示找到了值,但未找到指定的出现次数。
intWrap
答案 2 :(得分:0)
感谢您的回复。我正在学习有用的技术,这对您有很大的帮助。我实际上修复了基于@TimWilliams的第一个问题,将myCol设置为最后一列,因此它在第一列开始查找,并根据下面的内容添加了环绕检查。我还更改了msgBox,以根据每个@ VBasic2008返回一个值。
Function findField2(fieldName As String, Optional rowStart As Long = 0, Optional occurrence As Long = 1)
Dim Found As Range, lastRow As Long, count As Integer, myCol As Long
If rowStart = 0 Then rowStart = getHeaderRow()
myCol = 16384
For count = 1 To occurrence
Set Found = Rows(rowStart).Find(what:=fieldName, LookIn:=xlValues, lookat:=xlWhole, After:=Cells(rowStart, myCol))
' Check if nothing found or for wrap around and Nth occurrence not found
If Found Is Nothing Or count > 1 And Found.Column <= myCol Then
findField2 = 0
Exit Function
Else
myCol = Found.Column
End If
Next count
lastRow = Cells(Rows.count, Found.Column).End(xlUp).Row
findField2 = Found.Column
End Function
这是上面的findField函数中提到的getHeaderRow函数:
Function getHeaderRow() As Long
Dim i As Long, lastCol As Long, lastRow As Long
lastCol = Cells.Find("*", [a1], , , xlByColumns, xlPrevious).Column
lastRow = Cells.Find("*", [a1], , , xlByRows, xlPrevious).Row
i = 1
Do While Cells(i, lastCol).Value = ""
i = i + 1
If i > lastRow Then
i = 0
Exit Do
End If
Loop
getHeaderRow = i
End Function
答案 3 :(得分:0)
此版本使用FindNext
搜索第一个之后的事件。
它将搜索代码所在的工作簿的Sheet1
(ThisWorkbook
):
Sub Test()
Dim MyCell As Range
'Second occurrence default row.
Set MyCell = FindField("Date", Occurrence:=3)
If Not MyCell Is Nothing Then
MsgBox "Found in cell " & MyCell.Address & "." & vbCr & _
"Row: " & MyCell.Row & vbCr & "Column: " & MyCell.Column & vbCr & _
"Sheet: '" & MyCell.Parent.Name & "'" & vbCr & _
"Workbook: '" & MyCell.Parent.Parent.Name & "'", vbOKOnly + vbInformation
Else
MsgBox "Value not found."
End If
End Sub
Public Function FindField(FieldName As String, Optional RowStart As Long = 0, _
Optional Occurrence As Long = 1) As Range
Dim rFound As Range
Dim x As Long
Dim sFirstAdd As String
If RowStart = 0 Then RowStart = 1
x = 1
With ThisWorkbook.Worksheets("Sheet1").Rows(RowStart)
Set rFound = .Find( _
What:=FieldName, _
LookIn:=xlValues, _
LookAt:=xlWhole, _
After:=.Cells(RowStart, .Columns.Count))
If Not rFound Is Nothing Then
Set FindField = rFound
If Occurrence <> 1 Then
sFirstAdd = rFound.Address
Do
Set rFound = .FindNext(rFound)
x = x + 1
Loop While x <> Occurrence And rFound.Address <> sFirstAdd
If rFound.Address = sFirstAdd Then
Set FindField = Nothing
End If
End If
End If
End With
End Function