VBA Target.Address到两个单元格

时间:2016-05-31 19:34:41

标签: excel vba excel-vba

我必须使用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

虽然这是非常好的方法,但它无法运行。没有错误或弹出任何消息框。因此,请检查它是否是影响双重过滤器代码的第一个过滤器的代码。

非常感谢!

4 个答案:

答案 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