Excel VBA在命令按钮上显示/隐藏图像或形状单击事件对数据进行排序

Excel VBA在命令按钮上显示/隐藏图像或形状单击事件对数据进行排序,excel,vba,click,show-hide,shapes,Excel,Vba,Click,Show Hide,Shapes,我正在开发一个程序,它有多个数据列,可以按多个列进行排序。对于美学,我使用命令按钮单击事件以升序或降序切换排序。我的代码非常简单。我使用“向上”箭头和“向下”箭头的图像作为上升/下降指示器。所有图像都在工作表上,根据排序方法,“单击”事件会显示或隐藏相应的图像。编码工作正常,但有一个问题我没有考虑。当用户单击按钮进行排序时,该箭头会正确显示和隐藏该列,但其他列仍会显示箭头,这可能会混淆用户。我想隐藏除正在排序的列中的图像/箭头之外的其他图像/箭头 请参见所附图片以了解说明 在上图中,如果再次按

我正在开发一个程序,它有多个数据列,可以按多个列进行排序。对于美学,我使用命令按钮单击事件以升序或降序切换排序。我的代码非常简单。我使用“向上”箭头和“向下”箭头的图像作为上升/下降指示器。所有图像都在工作表上,根据排序方法,“单击”事件会显示或隐藏相应的图像。编码工作正常,但有一个问题我没有考虑。当用户单击按钮进行排序时,该箭头会正确显示和隐藏该列,但其他列仍会显示箭头,这可能会混淆用户。我想隐藏除正在排序的列中的图像/箭头之外的其他图像/箭头

请参见所附图片以了解说明

在上图中,如果再次按下播放器ID命令按钮,向上箭头将隐藏,向下箭头将可见,但其他箭头将保持不变。我只希望列被排序以显示箭头

下面的代码在工作表模块中使用命令按钮单击事件

Private Sub cmbAgentID_Click()

    If ActiveSheet.Shapes.Range(Array("picAgentIDUp")).Visible = False Then
        Call SortByAgentAsc 'sort ascending
        ActiveSheet.Shapes.Range(Array("picAgentIDUp")).Visible = True
        ActiveSheet.Shapes.Range(Array("picAgentIDDown")).Visible = False
    Else
        Call SortByAgentDes 'sort descending
        ActiveSheet.Shapes.Range(Array("picAgentIDDown")).Visible = True
        ActiveSheet.Shapes.Range(Array("picAgentIDUp")).Visible = False
    End If
End Sub
Private Sub cmbAllHands_Click()
    
    If ActiveSheet.Shapes.Range(Array("picAllHandsUp")).Visible = False Then
        Call SortByHandsAsc 'sort ascending
        ActiveSheet.Shapes.Range(Array("picAllHandsUp")).Visible = True
        ActiveSheet.Shapes.Range(Array("picAllHandsDown")).Visible = False
    Else
        Call SortByHandsDes 'sort descending
        ActiveSheet.Shapes.Range(Array("picAllHandsDown")).Visible = True
        ActiveSheet.Shapes.Range(Array("picAllHandsUp")).Visible = False
    End If
        
End Sub
Private Sub cmbCashHands_Click()

    
    If ActiveSheet.Shapes.Range(Array("picCashUp")).Visible = False Then
        Call SortByCashAsc 'sort ascending
        ActiveSheet.Shapes.Range(Array("picCashUp")).Visible = True
        ActiveSheet.Shapes.Range(Array("picCashDown")).Visible = False
    Else
        Call SortByCashDes 'sort descending
        ActiveSheet.Shapes.Range(Array("picCashDown")).Visible = True
        ActiveSheet.Shapes.Range(Array("picCashUp")).Visible = False
    End If
        
End Sub
Private Sub cmbEmbers_Click()
    
    If ActiveSheet.Shapes.Range(Array("picEmbersUp")).Visible = False Then
        Call SortByEmbersAsc 'sort ascending
        ActiveSheet.Shapes.Range(Array("picEmbersUp")).Visible = True
        ActiveSheet.Shapes.Range(Array("picEmbersDown")).Visible = False
    Else
        Call SortByEmbersDes 'sort descending
        ActiveSheet.Shapes.Range(Array("picEmbersDown")).Visible = True
        ActiveSheet.Shapes.Range(Array("picEmbersUp")).Visible = False
    End If
    
End Sub
Private Sub cmbFees_Click()
            
    If ActiveSheet.Shapes.Range(Array("picFeeUp")).Visible = False Then
        Call SortByFeeAsc 'sort ascending
        ActiveSheet.Shapes.Range(Array("picFeeUp")).Visible = True
        ActiveSheet.Shapes.Range(Array("picFeeDown")).Visible = False
    Else
        Call SortByFeeDes 'sort descending
        ActiveSheet.Shapes.Range(Array("picFeeDown")).Visible = True
        ActiveSheet.Shapes.Range(Array("picFeeUp")).Visible = False
    End If
        
End Sub
有什么建议吗?我一直在寻找ShapeRange,这对我和ShapeArray来说是新的,但还没有找到我要找的东西

-------更新了下面的代码,但建议的改进不起作用-------

创建“旋转它”子对象,并将宏指定给单个箭头

Sub RotateIt()
  
Dim s As Shape: Set s = ActiveSheet.Shapes(Application.Caller)
    
    If s.Rotation = 0 Then
        s.Rotation = 180
    Else
        s.Rotation = 0
    End If
    
End Sub
创建了1个子排序,我想我的问题在这里

Sub SortByEverything(sortKey As Range, Optional boolAsc As Boolean)
  
  Dim sh As Worksheet: Set sh = ActiveSheet
  Dim lastrow As Long: lastrow = Cells(Rows.Count, 2).End(xlUp).Row
  Dim rng As Range: Set rng = sh.Range("B3:M" & lastrow)
  
    If boolAsc Then
        With rng 'your existing code for ACENDING sorting type, but using supplied sortKey...
            .Sort Key1:=sortKey, Order1:=xlAscending, Header:=xlYes
        End With
        Debug.Print "Sort Ascending..."
    Else
        With rng 'your existing code for ACENDING sorting type, but using supplied sortKey...
            .Sort Key1:=sortKey, Order1:=xlAscending, Header:=xlYes
        End With
        Debug.Print "Sort Descending..."
    End If
    
End Sub
已创建类模块按钮名

Option Explicit

Public WithEvents cmdButton As MSForms.CommandButton

创建工作表激活子项

Option Explicit

Private arrEvents As Collection


请尝试下一种方法。创建要由所有按钮调用的
单击
事件:

Sub HideArrows(sh As Worksheet)
 Dim s As Shape
    For Each s In sh.Shapes
        If Right(s.Name, 2) = "Up" Or _
            Right(s.Name, 4) = "Down" Then s.Visible = msoFalse
    Next
End Sub
然后以以下方式使用现有代码:

Private Sub cmbAgentID_Click() 'proceed in a similar way to all the other click events
  Dim sh As Worksheet: Set sh = ActiveSheet
  
    HideArrows sh
    If sh.Shapes.Range(Array("picAgentIDUp")).Visible = False Then
        Call SortByAgentAsc 'sort ascending
        sh.Shapes.Range(Array("picAgentIDUp")).Visible = True
    Else
        Call SortByAgentDes 'sort descending
        sh.Shapes.Range(Array("picAgentIDDown")).Visible = True
    End If
End Sub
编辑:请尝试下一种不同的方法。它非常紧凑标准模块中的下一个代码将是所有必要的代码

  • 创建单个(向上)箭头形状并将其命名为“箭头”

  • 每个(表单类型)按钮将针对相同的
    子项
    ,因此为所有按钮分配下一个代码。对于ActiveX按钮,我将在结尾展示方法(稍微复杂一点,但不会太多):

  • 使用下一步内置的排序
    Subs
    。他们将根据每个按下的按钮位置接收分拣键:
  • 要更改箭头方向/排序类型,请为“箭头”形状指定下一个代码:
  • 下一个方法是:按下按钮时,“箭头”形状将移动到其右侧。根据其
    旋转
    属性,排序将按升序或降序进行。然后将调整箭头旋转。如果它仍然是向下的,并且下次,对于不同的列,您需要按降序排序,只需单击箭头形状,它将根据相应的排序类型进行旋转。您只需要一个排序
    Sub
    告知有关排序键和排序类型的

  • 对于ActiveX按钮,
    Application.Coller
    不会返回调用子名称的形状,并且需要类事件包装器
  • a) 插入一个类模块,将其命名为
    ButtonName
    ,然后复制下一个代码:

    Option Explicit
    
    Public WithEvents cmdButton As MSForms.CommandButton
    
    Public Sub cmdButton_Click()
        Dim sArr As Shape: Set sArr = ActiveSheet.Shapes("Arrow")
        
        sArr.top = cmdButton.top: sArr.left = cmdButton.left + cmdButton.width
        If sArr.Rotation = 0 Then
            SortByEverything cmdButton.TopLeftCell, True
            sArr.Rotation = 180
        Else
            SortByEverything cmdButton.TopLeftCell
            sArr.Rotation = 0
        End If
    End Sub
    
    注意:所有ActiveX按钮都不需要单击事件(对于此特定任务)

    b) 在图纸级别模块中创建一个私有变量。除此之外,在声明区域:

         Public arrEvents As Collection
    
    c) 使用
    工作表\u Activate
    事件(当然在保留按钮的工作表中),为所有ActiveX类型按钮初始化类:

    Private Sub Worksheet_Activate()
     Dim ActXButEvents As ButtonName, shp As Shape
    
     Set arrEvents = New Collection
    
     For Each shp In Me.Shapes
        If shp.Type = msoOLEControlObject Then
            If TypeOf shp.OLEFormat.Object.Object Is MSForms.CommandButton Then
                Set ActXButEvents = New ButtonName
                Set ActXButEvents.cmdButton = shp.OLEFormat.Object.Object
                arrEvents.aDD ActXButEvents
            End If
        End If
     Next
    End Sub
    
    注意:当您有代码时,如果不触发工作表激活事件,则无法按下工作表上的按钮。但是,在代码准备过程中,需要激活另一个工作表,然后重新激活它。只是为了触发前面提到的事件


    如果感兴趣,请检查并发送一些反馈。

    请尝试下一种方法。创建要由所有按钮调用的
    单击
    事件:

    Sub HideArrows(sh As Worksheet)
     Dim s As Shape
        For Each s In sh.Shapes
            If Right(s.Name, 2) = "Up" Or _
                Right(s.Name, 4) = "Down" Then s.Visible = msoFalse
        Next
    End Sub
    
    然后以以下方式使用现有代码:

    Private Sub cmbAgentID_Click() 'proceed in a similar way to all the other click events
      Dim sh As Worksheet: Set sh = ActiveSheet
      
        HideArrows sh
        If sh.Shapes.Range(Array("picAgentIDUp")).Visible = False Then
            Call SortByAgentAsc 'sort ascending
            sh.Shapes.Range(Array("picAgentIDUp")).Visible = True
        Else
            Call SortByAgentDes 'sort descending
            sh.Shapes.Range(Array("picAgentIDDown")).Visible = True
        End If
    End Sub
    
    编辑:请尝试下一种不同的方法。它非常紧凑标准模块中的下一个代码将是所有必要的代码

  • 创建单个(向上)箭头形状并将其命名为“箭头”

  • 每个(表单类型)按钮将针对相同的
    子项
    ,因此为所有按钮分配下一个代码。对于ActiveX按钮,我将在结尾展示方法(稍微复杂一点,但不会太多):

  • 使用下一步内置的排序
    Subs
    。他们将根据每个按下的按钮位置接收分拣键:
  • 要更改箭头方向/排序类型,请为“箭头”形状指定下一个代码:
  • 下一个方法是:按下按钮时,“箭头”形状将移动到其右侧。根据其
    旋转
    属性,排序将按升序或降序进行。然后将调整箭头旋转。如果它仍然是向下的,并且下次,对于不同的列,您需要按降序排序,只需单击箭头形状,它将根据相应的排序类型进行旋转。您只需要一个排序
    Sub
    告知有关排序键和排序类型的

  • 对于ActiveX按钮,
    Application.Coller
    不会返回调用子名称的形状,并且需要类事件包装器
  • a) 插入一个类模块,将其命名为
    ButtonName
    ,然后复制下一个代码:

    Option Explicit
    
    Public WithEvents cmdButton As MSForms.CommandButton
    
    Public Sub cmdButton_Click()
        Dim sArr As Shape: Set sArr = ActiveSheet.Shapes("Arrow")
        
        sArr.top = cmdButton.top: sArr.left = cmdButton.left + cmdButton.width
        If sArr.Rotation = 0 Then
            SortByEverything cmdButton.TopLeftCell, True
            sArr.Rotation = 180
        Else
            SortByEverything cmdButton.TopLeftCell
            sArr.Rotation = 0
        End If
    End Sub
    
    注意:所有ActiveX按钮都不需要单击事件(对于此特定任务)

    b) 创建Pri
         Public arrEvents As Collection
    
    Private Sub Worksheet_Activate()
     Dim ActXButEvents As ButtonName, shp As Shape
    
     Set arrEvents = New Collection
    
     For Each shp In Me.Shapes
        If shp.Type = msoOLEControlObject Then
            If TypeOf shp.OLEFormat.Object.Object Is MSForms.CommandButton Then
                Set ActXButEvents = New ButtonName
                Set ActXButEvents.cmdButton = shp.OLEFormat.Object.Object
                arrEvents.aDD ActXButEvents
            End If
        End If
     Next
    End Sub
    
    Private Sub cmbAgentID_Click()
        
    Dim sh As Worksheet: Set sh = ActiveSheet
                
        If sh.Shapes.Range(Array("picAgentIDUp")).Visible = msoFalse Then
            hidedownarrows sh
            Call SortByAgentAsc 'sort ascending
            With sh.Shapes
                .Range(Array("picAgentIDUp")).Visible = msoTrue
                .Range(Array("picCashUp", "picAllHandsUp", "picEmbersUp", "picRBAmtUp", "PicRBUp", "picFeeUp", "picIDUp")).Visible = msoFalse
            End With
        Else
            HideupArrows sh
            Call SortByAgentDes 'sort descending
            With sh.Shapes
                .Range(Array("picAgentIDDown")).Visible = msoTrue
                .Range(Array("picCashdown", "picAllHandsdown", "picEmbersdown", "picRBAmtdown", "PicRBdown", "picFeedown", "picIDdown")).Visible = msoFalse
            End With
        End If
        
    End Sub
    Private Sub cmbAllHands_Click()
        
        Dim sh As Worksheet: Set sh = ActiveSheet
        
        If sh.Shapes.Range(Array("picAllHandsUp")).Visible = msoFalse Then
            hidedownarrows sh
            Call SortByHandsAsc 'sort ascending
            With sh.Shapes
                .Range(Array("picAllHandsUp")).Visible = msoTrue
                .Range(Array("picCashUp", "picAgentIDUp", "picEmbersUp", "picRBAmtUp", "PicRBUp", "picFeeUp", "picIDUp")).Visible = msoFalse
            End With
        Else
            HideupArrows sh
            Call SortByHandsDes 'sort descending
            With sh.Shapes
                .Range(Array("picAllHandsDown")).Visible = msoTrue
                .Range(Array("picCashdown", "picAgentIDdown", "picEmbersdown", "picRBAmtdown", "PicRBdown", "picFeedown", "picIDdown")).Visible = msoFalse
            End With
        End If
                    
    End Sub
    Private Sub cmbCashHands_Click()
    
        Dim sh As Worksheet: Set sh = ActiveSheet
        
        If sh.Shapes.Range(Array("picCashUp")).Visible = msoFalse Then
            hidedownarrows sh
            Call SortByCashAsc 'sort ascending
            With sh.Shapes
                .Range(Array("picCashUp")).Visible = msoTrue
                .Range(Array("picAllHandsUp", "picAgentIDUp", "picEmbersUp", "picRBAmtUp", "PicRBUp", "picFeeUp", "picIDUp")).Visible = msoFalse
            End With
        Else
            HideupArrows sh
            Call SortByCashDes 'sort descending
            With sh.Shapes
                .Range(Array("picCashDown")).Visible = msoTrue
                .Range(Array("picAllHandsDown", "picAgentIDdown", "picEmbersdown", "picRBAmtdown", "PicRBdown", "picFeedown", "picIDdown")).Visible = msoFalse
            End With
            End If
        
    End Sub
    Private Sub cmbEmbers_Click()
        
        Dim sh As Worksheet: Set sh = ActiveSheet
        
        If sh.Shapes.Range(Array("picEmbersUp")).Visible = msoFalse Then
            hidedownarrows sh
            Call SortByEmbersAsc 'sort ascending
            With sh.Shapes
                .Range(Array("picEmbersUp")).Visible = msoTrue
                .Range(Array("picAllHandsUp", "picAgentIDUp", "picCashUp", "picRBAmtUp", "PicRBUp", "picFeeUp", "picIDUp")).Visible = msoFalse
            End With
        Else
            HideupArrows sh
            Call SortByEmbersDes 'sort descending
            With sh.Shapes
                .Range(Array("picEmbersDown")).Visible = msoTrue
                .Range(Array("picAllHandsDown", "picAgentIDdown", "picCashDown", "picRBAmtdown", "PicRBdown", "picFeedown", "picIDdown")).Visible = msoFalse
            End With
        End If
        
    End Sub
    Private Sub cmbFees_Click()
                
        Dim sh As Worksheet: Set sh = ActiveSheet
    
        If sh.Shapes.Range(Array("picFeeUp")).Visible = msoFalse Then
            hidedownarrows sh
            Call SortByFeeAsc 'sort ascending
            With sh.Shapes
                .Range(Array("picFeeUp")).Visible = msoTrue
                .Range(Array("picAllHandsUp", "picAgentIDUp", "picCashUp", "picRBAmtUp", "PicRBUp", "picEmbersUp", "picIDUp")).Visible = msoFalse
            End With
        Else
            HideupArrows sh
            Call SortByFeeDes 'sort descending
            With sh.Shapes
                .Range(Array("picFeeDown")).Visible = msoTrue
                .Range(Array("picAllHandsDown", "picAgentIDdown", "picCashDown", "picRBAmtdown", "PicRBdown", "picEmbersDown", "picIDdown")).Visible = msoFalse
            End With
        End If
            
    End Sub
    
    Sub HideupArrows(sh As Worksheet)
    
    Dim s As Shape
    
       For Each s In sh.Shapes
           If Right(s.Name, 2) = "Up" Then
               s.Visible = msoFalse
           End If
       Next
    
    End Sub
    Sub hidedownarrows(sh As Worksheet)
    
    Dim s As Shape
    
        For Each s In sh.Shapes
            If Right(s.Name, 4) = "Down" Then
                s.Visible = msoFalse
            End If
        Next
        
    End Sub