您好,这是我的第一个问题,因此,我将尽我最大的努力来格式化。
下面没有特定单元格名称的快速说明
我正在尝试编写一个宏,用户在其中输入一个值(X),然后宏在一个单元格区域中搜索一个值(X),然后该宏返回3号空格中的单元格值值(X)的位置是。
使此问题无法解决的几件事是用户在Sheet1上输入了值,并且该值已通过公式移动到Sheet2,我似乎无法弄清楚如何使用Find值我正在搜索的宏中尚未定义。
造成这一困难的另一件事是,该范围也不是严格定义的,因为该列表可能比现在更长或更短,而且我不知道它何时会更改。因此,必须根据用户输入的列表开始搜索范围,并且需要继续搜索直到列表空白。
例如:Range。(“ C7:D10”)无法正常工作,因为用户可以输入新信息来更改工作范围,如下所述。
下面是带有进一步说明的屏幕截图
https://i.stack.imgur.com/wlnhg.jpg
因此在此屏幕截图中,单元格C3和D3是从Sheet1导入的值。
C3是(= Sheet1!B2)
D3是(= Sheet1!B3)
这个想法是宏运行并向下搜索A列,直到与C3匹配为止。
然后搜索功能移至两个单元格上方并向下搜索,直到与D3匹配或碰到空白为止。
我不知道如何让一个宏基于导入的值进行搜索,也不知道如何让它搜索这个我需要的奇怪范围。这个想法是,我工作的人可能会出现,并在C10下方添加一行并添加必要的信息,该宏仍然可以工作并搜索到C11,并且在告诉宏停止后会有空白。
搜索找到D3的匹配项后,它将与该匹配项相邻的值返回到顶部E3,F3和G3的相应单元格。
我希望这个问题能以人们能理解的方式提出,我很累,所以不能告诉我我写的东西是否有意义。谢谢您阅读我的文章,你们都很棒!
答案 0 :(得分:0)
Formulas Tab > Name Manager > Select Table/Change Name
来更改表的名称。具体来说,您将需要将名称更改为所需的列表名称。 (Table 1 Name = List1
和Table 2 Name = List2
)E3, F3, & G3
E3 = VLOOKUP(D3, Indirect(C3), 2, 0)
F3 = VLOOKUP(D3, Indirect(C3), 3, 0)
G3 = VLOOKUP(D3, Indirect(C3), 4, 0)
随着表大小的扩展,此信息将动态更新。您还可以根据需要添加任意数量的表格,此表格将继续有效。
在使用中,外观类似于
我最后的建议是将每个公式嵌套在IFERROR()
答案 1 :(得分:0)
感到疲倦的一个原因是,您在准备宰杀之前就尝试过杀戮。下面的解决方案需要一个小时的准备时间和10分钟的编码时间。将整个代码粘贴到标准代码模块中,然后从立即窗口(MatchRow
)或从您自己的代码中调用函数? MatchRow
,如测试过程中进一步所示。
Option Explicit
Enum Nws ' worksheet navigation
' 01 Mar 2019
NwsCriteriaRow = 3
NwsList = 1 ' Columns: (1 = A)
NwsID = 3
NwsNumber ' (undefined: assigns next integer)
End Enum
Function MatchRow() As Long
' 01 Mar 2019
' return 0 if not found
Dim Ws As Worksheet
Dim Rng As Range
Dim R As Long
' The ActiveWorkbook isn't necessarily ThisWorkbook
Set Ws = ActiveWorkbook.Worksheets("Sheet2") ' replace tab's name here
With Ws
Set Rng = .Range(.Cells(NwsCriteriaRow, NwsList), .Cells(.Rows.Count, NwsList).End(xlUp))
R = FindRow(.Cells(NwsCriteriaRow, NwsID).Value, Rng, True)
If R Then ' skip if no match was found
Set Rng = .Cells(R + 1, NwsID)
Set Rng = .Range(Rng, Rng.End(xlDown))
MatchRow = FindRow(.Cells(NwsCriteriaRow, NwsNumber).Value, Rng)
End If
End With
End Function
Private Function FindRow(Crit As Variant, _
Rng As Range, _
Optional ByVal SearchFromTop As Boolean) As Long
' 01 Mar 2019
' return 0 if not found
Dim Fun As Range
Dim StartCell As Long
With Rng
If SearchFromTop Then
StartCell = 1
Else
StartCell = .Cells.Count
End If
Set Fun = .Find(What:=Crit, _
After:=.Cells(StartCell), _
LookIn:=xlValues, _
LookAt:=xlWhole, _
MatchCase:=False)
End With
If Not Fun Is Nothing Then FindRow = Fun.Row
End Function
函数MatchRow
返回找到D3的Sheet2的行号,仅搜索D列中属于C3标识的列表的那部分。如果找不到列表或ID匹配,则该函数返回0。
您未指定要对找到的行执行的操作。下面的过程将从该行返回数据。您可能会使用该功能来寻址要写入的单元格。
Private Sub RetrieveData()
Dim R As Long
R = MatchRow
MsgBox "ID = " & Cells(R, NwsID).Value & vbCr & _
"Number = " & Cells(R, NwsNumber).Value
End Sub
仅用于测试上面的proc并没有指定工作表,因此从ActiveSheet返回假定为Sheet2的数据。
答案 2 :(得分:0)
Workbook Download(Dropbox)
Sub SearchTwice()
Const cSheet As String = "Sheet2" ' Source Worksheet Name
Const cList As String = "C3" ' List Cell Range Address
Const cName As String = "D3" ' Name Cell Range Address
Const cListCol As String = "A" ' List Column Letter
Const cNameCol As String = "C" ' Name Column Letter
Const cFirst As Long = 6 ' First Row
Const cCol As Long = 3 ' Number of Columns
Dim rng1 As Range ' Find List Cell Range
' Found Name Cell Range
Dim rng2 As Range ' Next List Cell Range
' Name Search Range
Dim strList As String ' List
Dim strName As String ' Name
' In Source Worksheet
With ThisWorkbook.Worksheets(cSheet)
' Write from List Cell Range to List.
strList = .Range(cList)
' Write from Name Cell Range to Name.
strName = .Range(cName)
' Check if Cell Ranges do NOT contain data.
If strList = "" Or strName = "" Then ' Inform user.
MsgBox "Missing List or Name.", vbCritical, "Missing data"
Exit Sub
End If
' In List Column
With .Columns(cListCol)
' Create a reference to Find List Cell Range (rng1) containing
' List (strList).
Set rng1 = .Find(strList, .Cells(cFirst - 1), xlValues, xlWhole)
' Check if List has not been found.
If rng1 Is Nothing Then ' Inform user and exit.
MsgBox "The list '" & strList & "' has not been found", _
vbCritical, "List not found"
Exit Sub
End If
' Create a reference to Next List Cell Range (rng2).
Set rng2 = .Find("*", .Cells(rng1.Row), xlValues, xlWhole)
End With
' In Name Column
With .Columns(cNameCol)
' Check if the row of Next List Cell Range (rng2) is greater than
' the row of List Cell Range (rng1) i.e. if a cell with a value
' has been found below List Cell Range (rng1) in List Column.
If rng2.Row > rng1.Row Then ' Next List Cell Range FOUND.
' Create a reference to Name Search Range (rng2) which spans
' from the cell below Find List Cell Range (rng1) to the cell
' above the Next List Cell Range (rng2), but in Name Column.
Set rng2 = .Cells(rng1.Row + 1).Resize(rng2.Row - rng1.Row - 1)
Else ' Next List Cell Range NOT found.
' Create a reference to Name Search Range (rng2) which spans
' from the cell below Find List Cell Range (rng1) to the bottom
' cell, but in Name column.
Set rng2 = .Cells(rng1.Row + 1).Resize(.Rows.Count - rng1.Row)
End If
End With
' In Name Search Range (rng2)
With rng2
' Create a reference to Found Name Cell Range (rng1).
Set rng1 = .Find(strName, .Cells(.Rows.Count), xlValues, xlWhole)
End With
' Check if Name has not been found.
If rng1 Is Nothing Then ' Inform user and exit.
MsgBox "The name '" & strName & "' has not been found", _
vbCritical, "Name not found"
Exit Sub
End If
' Remarks:
' Source Range is calculated by moving the Found Name Cell Range (rng1)
' one cell to the right and by resizing it by Number of Columns (cCol).
' Target Range is calculated by moving the Name Cell Range one cell
' to the right and by resizing it by Number of Columns (cCol).
' Copy values of Source Range to Target Range.
.Range(cName).Offset(, 1).Resize(, cCol) _
= rng1.Offset(, 1).Resize(, cCol).Value
End With
' Inform user of succes of the operation.
MsgBox "The name '" & strName & "' was successfully found in list '" & _
strList & "'. The corresponding data has been written to the " _
& "worksheet.", vbInformation, "Success"
End Sub
答案 3 :(得分:0)
我认为非VBA解决方案在这里是理想的选择,但是为了以防万一,我将在此单独列出。假设表中的任何值都不为空,这将适合您的情况。
Sub Test()
Dim ws As Worksheet: Set Worksheet = ThisWorkbook.Sheets("Sheet2")
Dim iList As Range, iName As Range
Dim aLR As Long, cLR As Long
aLR = ws.Range("A" & ws.Rows.Count).End(xlUp).Row
Set iList = ws.Range("A1:A" & aLR).Find(ws.Range("C3"), LookIn:=xlWhole)
If Not iList Is Nothing Then
cLR = iList.Offset(0, 2).End(xlDown).Row
Set iName = ws.Range(ws.Cells(iList.Row, 3), ws.Cells(cLR, 3)).Find(ws.Range("C4"), LookIn:=xlWhole)
If Not iName Is Nothing Then
ws.Range("E3:G3").Value = iName.Offset(0, 1).Resize(1, 3).Value
End If
End If
End Sub