[英]Lookup an alphanumeric value in a range of a cell in excel
現在存在這樣的 function。 顯示的公式:
結果:
要在不編輯單元格內容的情況下解決此問題,您實際上被迫做的是使用兩個向量(一個索引和一個值)構建一個數據集,然后查詢它以獲取您想要的內容到達一個索引。 這種情況下的數據集是一個非常參差不齊的 collections 數組 collections collections 的數組,至少,我會這樣做。 為了保持思路清晰,我為模塊制作了一個准對象 model:
在上述照片中,Collection Item 鍵位於大括號中。
因此,如果您想實現此 function,請將其放入您的數據所在的任何工作簿中的代碼模塊中。
快速免責聲明 - 以下代碼不是特別優雅或高效,但它確實完成了任務。
Option Explicit
' I'm not a fan of 0-based indexing in VBA, so this fixes it for me.
' You could go without, and doing so could be a good academic
' excercise on utilizing VBA for data management.
Private Function ChangeIndex(StrIn() As String) As String()
Dim i As Integer
Dim temp() As String
ReDim temp(1 To UBound(StrIn) + 1)
For i = 1 To UBound(StrIn) + 1
temp(i) = StrIn(i - 1)
Next i
ChangeIndex = temp
End Function
'Finds index of first numeric character in string
Private Function FindNumeric(ByVal StrIn As String) As Integer
Dim i As Integer
For i = 1 To Len(StrIn)
If IsNumeric(Mid(StrIn, i, 1)) Then
FindNumeric = i
Exit Function
End If
Next i
End Function
'Finds numeric components of textual range
Private Function FindRange(ByVal StrIn As String) As Integer()
Dim answer(1 To 2) As Integer
Dim num_pos As Integer
Dim dash_pos As Integer
Dim temp As String
Dim temp_two As String
dash_pos = InStr(1, StrIn, "-", vbBinaryCompare)
If dash_pos <> 0 Then
num_pos = FindNumeric(StrIn)
temp = Mid(StrIn, num_pos, Len(StrIn) - dash_pos - num_pos + 1)
answer(1) = CInt(temp)
temp = Mid(StrIn, dash_pos + 1, Len(StrIn) - dash_pos + 1)
num_pos = FindNumeric(temp) + dash_pos
temp = Mid(StrIn, num_pos, Len(StrIn) - dash_pos - (Len(StrIn) - num_pos))
answer(2) = CInt(temp)
Else
num_pos = FindNumeric(StrIn)
temp = Mid(StrIn, num_pos, Len(StrIn) - dash_pos - num_pos + 1)
answer(1) = CInt(temp)
answer(2) = answer(1)
End If
FindRange = answer
End Function
Public Function AlphaNumLU(Query As String, IndexVector As range, ValueVector As range) As Variant
Dim csvs() As String
Dim entries() As Collection
Dim alpha As Collection
Dim numeric As Collection
Dim temp As String
Dim q_alpha As String
Dim q_num As Integer
Dim entry As Variant
Dim raw_val As Variant
Dim i, j As Integer
Dim range() As Integer
Dim alpha_found As Boolean
'The bare minimum error handling
If IndexVector.count <> ValueVector.count Then
MsgBox Prompt:="Input vectors must be of same length"
AlphaNumLU = "#VALUE"
Exit Function
End If
'Import Indexes to collection of entries
ReDim entries(1 To IndexVector.count)
For i = 1 To IndexVector.count
Set entries(i) = New Collection
temp = IndexVector(i, 1).Value
entries(i).Add Item:="Entry", Key:="Label"
entries(i).Add Item:=temp, Key:="Index"
Next i
'Import Values as Comma Delineated arrays of string
For i = 1 To ValueVector.count
temp = ValueVector(i, 1).Value
csvs = Split(temp, ",")
csvs = ChangeIndex(csvs)
entries(i).Add csvs, "RawVals"
Next i
'Construct Textual Components
For Each entry In entries
For Each raw_val In entry(3)
i = FindNumeric(raw_val) - 1
temp = Mid(raw_val, 1, i)
If entry.count < 3 Then
MsgBox "Entry should be composed of items Label, Index, alpha..."
Exit Function
ElseIf entry.count = 3 Then
Set alpha = New Collection
alpha.Add Item:="text comp", Key:="Label"
alpha.Add Item:=temp, Key:="Index"
entry.Add alpha
Else
alpha_found = False
For i = 4 To entry.count
If entry(i)(2) = temp Then
alpha_found = True
Exit For
End If
Next i
If Not alpha_found Then
Set alpha = New Collection
alpha.Add Item:="text comp", Key:="Label"
alpha.Add Item:=temp, Key:="Value"
entry.Add alpha
End If
End If
Next raw_val
Next entry
'Construct Numerical Components
For Each entry In entries
For Each raw_val In entry(3)
Set numeric = New Collection
numeric.Add Item:="numeric", Key:="Label"
range = FindRange(raw_val)
numeric.Add Item:=range(1), Key:="Min"
numeric.Add Item:=range(2), Key:="Max"
temp = Left(raw_val, FindNumeric(raw_val) - 1)
For i = 4 To entry.count
If entry(i)(2) = temp Then
entry(i).Add numeric
End If
Next i
Next raw_val
Next entry
'And Finally, Parse the Massive object we just created for the query.
q_alpha = Left(Query, FindNumeric(Query) - 1)
q_num = CInt(Right(Query, Len(Query) - Len(q_alpha)))
For Each entry In entries
For i = 4 To entry.count
If q_alpha = entry(i)(2) Then
For j = 3 To entry(i).count
If q_num >= entry(i)(j)(2) And q_num <= entry(i)(j)(3) Then
AlphaNumLU = entry(2)
Exit Function
End If
Next j
End If
Next i
Next entry
'Give notice if the value doesn't exist
AlphaNumLU = "Not Found"
End Function
所以這個故事的寓意是——修改數據呈現給查找 function 的方式可能更明智,正如@teylyn 所提到的。 VBA 可以完成,但不一定漂亮。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.