我必须使用VBA在Excel中构建嵌套的过滤器结构。该方法是构建包含排序索引的两个数据验证列表。我有三个可能的索引索引,即lastName,FirstName和Company。因为在sort函数中不允许在排序范围之外引用索引。我构建了6种可能的索引组合,例如下面的内容。
Sub Macro_Sort1()
Sheets("Reports").Range("F1:CT10000").Sort Key1:=Sheets("Reports").Range("I1"), Order1:=xlAscending, Key2:=Sheets("Reports").Range("J1"), Order1:=xlAscending, Header:=xlYes
End Sub
现在我需要将这个宏分配给这两个数据验证列表,比如
If Target.Address = "$B$1" and "$B$2" Then
Select Case Target.Value2
Case "Last" and "First"
Call Macro_Sort1
Case "Last" and "Company"
Call Macro_Sort2
Case "First" and "Last"
Call Macro_Sort3
Case "First" and "Company"
Call Macro_Sort4
Case "Company" and "Last"
Call Macro_Sort5
Case "Company" and "First"
Call Macro_Sort6
End Select
End if
End Sub
然而,显然它告诉我Target.Address句子有关于那么的错误。
请帮我弄清楚是否有其他办法来实现这一目标。
提前致谢!
更新
正如我所提到的,我有两个过滤器,第一个可以独立使用,它有如下所示的宏分配:
Sub Macro_Sort1()
Sheets("Reports").Range("F1:CT10000").Sort Key1:=Sheets("Reports").Range("I1"), Header:=xlYes, Order1:=xlAscending
End Sub
所以在两个过滤器的代码之前会有这样的代码:
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Address = "$B$17" Then
Select Case Target.Value2
Case "Last"
Call Macro_Sort1
Case "First"
Call Macro_Sort2
Case "Company"
Call Macro_Sort3
End Select
根据一些建议,我在前一部分后添加了这部分。
ElseIf Target.Address(0, 0) = "$B$17" Or Target.Address(0, 0) = "$B$18" Then
SortUsingDataValidation Range("B17").Value, Range("B18").Value
End If
End Sub
Private Sub SortUsingDataValidation(sFirst As String, sSecond As String)
Dim oDict As Object
Set oDict = CreateObject("Scripting.Dictionary")
With ThisWorknook.shhets("Reports")
Set oDict("Last") = .Range("I1")
Set oDict("First") = .Range("J1")
Set oDict("Company") = .Range("K1")
If oDict.exists(sFirst) And oDict.exists(sSecond) Then
.Range("F1:CT10000").Sort Key1:=oDict(sFirst), Order1:=xlAscending, key2:=oDict(sSecond), Order1:=xlAscending, Header:=xlYes
End If
End With
End Sub
虽然这是非常好的方法,但它无法运行。没有错误或弹出任何消息框。因此,请检查它是否是影响双重过滤器代码的第一个过滤器的代码。
非常感谢!
答案 0 :(得分:4)
有几件事;
地址为" B1:B2"
要使用Select Case进行多项测试,我们要搜索True并将其格式化为IF / ElseIF:
If target.Address(0, 0) = "B1:B2" Then
Select Case True
Case Range("B1") = "Last" And Range("B2") = "First"
Call Macro_Sort1
Case Range("B1") = "Last" And Range("B2") = "Company"
Call Macro_Sort2
Case Range("B1") = "First" And Range("B2") = "Last"
Call Macro_Sort3
Case Range("B1") = "First" And Range("B2") = "Company"
Call Macro_Sort4
Case Range("B1") = "Company" And Range("B2") = "Last"
Call Macro_Sort5
Case Range("B1") = "Company" And Range("B2") = "First"
Call Macro_Sort6
End Select
End If
答案 1 :(得分:4)
编辑:
将Application.Transpose()
方法添加到Target
范围,因为B1:B2
是一列“垂直”范围,而Join()
期望一个数组对应于一个 - 行“水平”范围
添加了一些代码“风味”来处理不同的环境
改变方法
If Target.Address = "$B$1:$B$2" Then
Dim strng As String
Dim pos as Long
strng = "1LastFirst,2LastCompany,3FirstLast,4FirstCompany,5CompanyLast,6CompanyLast"
pos = Instr(strng,Join (Application.Transpose(Target),""))
If pos > 0 then Application.Run "Macro_Sort" & Mid(strng,pos-1,1)
End If
最后一些环境建议:
如果您在Worksheet事件处理程序中运行此代码,则
If Target.Address = "$B$1:$B$2"
只能在True
处理程序中Worksheet_SelectionChange
,而处理Target
范围参数的其他相关处理程序只会检测到一个单元格范围
例如,如果您需要在Worksheet_Change
事件处理程序中运行它,那么您需要将检查更改为某些:
If Not Intersect(Target, Range ("B1:B2")) Is Nothing Then
在许多其他不同情况下也可以这样做
Application.Run
方法调用的子方法必须放在任何模块中,但不能放在工作表中
答案 2 :(得分:2)
If Target.Address = "$B$1" And "$B$2" Then
这是一个语法错误,因为If {boolean-expression} Then
需要一个布尔表达式 - 而且你已经将VBA与该表达式的And {string-literal}
部分混淆了。
您可以使用And
关键字构建布尔表达式,如下所示:
{boolean-expression} And {boolean-expression}
换句话说,你可以做到:
If Target.Address = "$B$1" And Target.Address = "$B$2" Then
但正如您所怀疑的那样,该逻辑必然会始终返回False
,因为如果Target.Address
等于"$B$1"
,那么也 等于"$B$2"
。
Scott's answer有剩下的解决方案。
答案 3 :(得分:1)
我将添加另一种方法,因为拥有6个不同的宏来完成同样的事情通常不是一个好主意。它会起作用,但需要维护更多的代码,使未来的更改变得更加困难。
在下面的代码中,验证框的值被传递到一个函数中,该函数(1)将每个值链接到相应的范围,(2)根据相应的范围进行排序。
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Address(0, 0) = "B1" Or Target.Address(0, 0) = "B2" Then
SortUsingDataValidation Range("B1").Value, Range("B2").Value
End If
End Sub
Private Sub SortUsingDataValidation(sFirst As String, sSecond As String)
Dim oDict As Object
'Create a dictionary (or any collection) to hold references from a data validation
'String to its corresponding cell reference
Set oDict = CreateObject("Scripting.Dictionary")
With ThisWorkbook.Sheets("Reports")
Set oDict("First") = .Range("I1")
Set oDict("Last") = .Range("J1")
Set oDict("Company") = .Range("K1")
If oDict.exists(sFirst) And oDict.exists(sSecond) Then
.Range("F1:CT10000").Sort Key1:=oDict(sFirst), Order1:=xlAscending, Key2:=oDict(sSecond), Order1:=xlAscending, Header:=xlYes
End If
End With
End Sub