现在有这样的功能。显示的公式:
Lookup Formulae
结果:
Successful results
要在不编辑单元格内容的情况下解决此问题,您实际上不得不做的是使用两个向量(一个索引和一个值)构建一个数据集,然后查询它以获取您想要的内容为了得出一个索引。在这种情况下,数据集是一个非常参差不齐的集合集合集合,至少,我会这样做。为了保持思路清晰,我为该模块制作了一个准对象模型:
Quasi Object Model
在上述照片中,Collection Item 键位于大括号中。
因此,如果您想实现此功能,请将其放入您的数据所在的任何工作簿中的代码模块中。
快速免责声明 - 以下代码不是特别优雅或高效,但确实可以完成任务。
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
所以故事的寓意是 - 修改数据呈现给 @teylyn 提到的查找函数的方式可能更明智。 VBA 可以搞定,但不一定漂亮。