I have created a multipage user form which dynamically populates with a set of identical frames and each of them has 2 option buttons based on previous user selections. I am trying to check if at least one of the option buttons is selected within each frame but don't seem to access the option buttons in code even through I know what their names will be. I will then be transferring the selection to a worksheet so need to be able to see what they have selected. Any help would be appreciated, I use VBA for excel infrequently so its always a struggle to be honest.
I'm getting closer, I've used this code of another post and changed it slightly while I trial what I am doing. Getting there slowly. :)
I'm not sure what some of the Class modules part is doing but its working.
Forms: Userform1
Option Explicit
Friend Sub OptionButtonSngClick(o As MSForms.OptionButton)
Dim cControlCheck As MSForms.Control
Dim cControlCheck1 As MSForms.Control
Dim cControlFrame As MSForms.Control
Dim strName As String
If Left(o.Name, 2) = "qN" Then
o.BackColor = RGB(256, 0, 0)
ElseIf Left(o.Name, 2) = "qY" Then
o.BackColor = RGB(0, 256, 0)
End If
For Each cControlCheck In UserForm1.Controls
If TypeName(cControlCheck) = "Frame" Then
For Each cControlCheck1 In Me.Controls(cControlCheck.Name).Controls
If TypeName(cControlCheck1) = "OptionButton" Then
If cControlCheck1 = False Then
cControlCheck1.BackColor = RGB(240, 240, 240)
End If
End If
Next
End If
Next
End Sub
Friend Sub cmdCheck_Click()
Dim cControlCheck2 As MSForms.Control
Dim cControlCheck3 As MSForms.Control
Dim cCollection As Collection
Set cCollection = New Collection
For Each cControlCheck2 In UserForm1.Controls
If TypeName(cControlCheck2) = "Frame" Then
For Each cControlCheck3 In Me.Controls(cControlCheck2.Name).Controls
If TypeName(cControlCheck3) = "OptionButton" Then
cCollection.Add cControlCheck3
End If
Next
End If
Next
If cCollection(1).Value = False And cCollection(2).Value = False Then
MsgBox ("Make a selection")
End If
End Sub
Class Module: OPtionButtonEvents
Option Explicit
Private WithEvents ob As MSForms.OptionButton
Private CallBackParent As UserForm1
Private CallBackParent1 As UserForm1
Private Sub ob_Change()
End Sub
Private Sub ob_Click()
Call CallBackParent.OptionButtonSngClick(ob)
End Sub
Private Sub ob_DblClick(ByVal Cancel As MSForms.ReturnBoolean)
Call CallBackParent.OptionButtonDblClick(ob)
End Sub
Friend Sub WatchControl(oControl As MSForms.OptionButton, oParent As UserForm1)
Set ob = oControl
Set CallBackParent = oParent
End Sub
Related
I have a Sub to change the background color of OptionButton in a group when clicked but i can't get this work fluently without any delay when switch the colorm too slow. Is there better aproach?
There are 50 OptionButtons with a unique caption each
class module
Public WithEvents Opt As MSForms.OptionButton
Private Sub Opt_Click()
Application.ScreenUpdating = False
Call toggleColor(Opt)
Application.ScreenUpdating = True
End Sub
Sub toggleColor(opt As Object)
For Each ctl In Worksheets("controls").OLEObjects
If TypeName(ctl.Object) = "OptionButton" Then
If ctl.Object.Caption <> optCaption.Caption Then
ctl.Object.BackColor = &H80000011
Else
opt.BackColor = &H80000016
End If
End If
Next ctl
End Sub
Seems like you only need to set the color for 2 options, not 50 - you just need to remember between calls which one is the odd one out, reset that one, then set the color for opt.
ToggleColor insn't instance-specific (since you're passing in opt), so that could be in a regular module and re-worked to something like:
Sub toggleColor(opt As Object)
Static optPrev As Object 'previous selection (if any)
If Not optPrev Is Nothing Then
optPrev.BackColor = &H80000011 'un-flag previous
End If
opt.BackColor = &H80000016 'flag the clicked one
Set optPrev = opt 'remember it for next time
End Sub
i really need some help, im new to VBA programming and just learn all by myself.
Thx for all Help.
What is my problem ?
I have more than 1 Userforms in my Tool and every Userform contains alot of Buttons some Buttons the same on other Userforms and some different.
if i click a button in a Userform, the class cant give my userform.name as a variable to the next module.
in the Code "Class" sUserform is alltime "nothing"
My Code
Userform
Option Explicit
Private myBtn As clsCMD
Private Sub UserForm_Activate()
modUI.ufGETICON Me
End Sub
Private Sub UserForm_Initialize()
modMSG.ufINFO
modAUTOOPEN.Workbook_Open Me
Dim ctrl As Control
For Each ctrl In frmMain.Controls
If TypeOf ctrl Is MSForms.CommandButton Then
Set myBtn = New clsCMD
Set myBtn.Button = ctrl
End If
Next
End Sub
Class
Option Explicit
Public WithEvents Button As MSForms.CommandButton
Private Sub Class_Initialize()
Static collButton As New Collection
collButton.Add Me
End Sub
Private Sub Button_Click()
Dim sButton As String
sButton = Button.Name
CMDTEST *sUserform*, Button
End Sub
Private Sub CMDTEST(*sUserform As Object*, sButton As Object)
If sButton.Name = "cmd_Admin" Then
modCMD.cmd_Admin
End If
If sButton.Name = "cmd_OItem" Then
modCMD.cmd_OItem sUserform
End If
End Sub
Modul
Option Explicit
Public sUserform As Object
Public Sub cmd_Admin()
Dim sAnswer As String
sAnswer = InputBox("Passwort f?r den Zugang zum Adminbereich eingeben:", "Zugang Adminbereich")
If sAnswer = sPASS Then
Unload frmMain
frmMain.Hide
ElseIf sAnswer = "" Then
Exit Sub
Else
MsgBox "Inkorrektes Passwort eingegeben", vbInformation + vbOKOnly, "Passwortabfrage negativ"
End If
Application.Visible = True
End Sub
Public Sub cmd_OItem(sUseform As Object)
sUserform.Hide
frmOnIt.Show
End Sub
It's difficult to give you a precise answer without seeing how you want to apply this code across your Userforms.
If, for example, you're running the loops on each Userform, then couldn't you just add a Userform property to your class and pass in the appropriate Userform?
For Each ctrl In frmMain.Controls
If TypeOf ctrl Is MSForms.CommandButton Then
Set myBtn = New clsCMD
With myBtn
Set .Owner = frmMain
Set .Button = ctrl
End With
End If
Next
Otherwise, I guess you'd just have to run up the control ladder until you find a Userform:
Private Function GetUserFormName(ctrl As Object) As String
Do
Set ctrl = ctrl.Parent
Loop Until TypeOf ctrl.Parent Is MSForms.UserForm And Not TypeOf ctrl.Parent Is MSForms.Frame
GetUserFormName = ctrl.Parent.Name
End Function
So your routine would contain code something like:
Private Sub CMDTEST(sButton As Object)
Dim n As String
n = GetUserFormName(sButton)
End Sub
I solved the problem now and I'd like to hear your feedback if it's a good way or not. Maybe there are some improvements to do?
You have to know this project is huge and i have more than 20 Userforms and over all Userforms more than 300 buttons.
Most of these buttons are like a Menu (laststep, nextstep, finish, cancel, OItem, Test, and some more). These are all doing the same every time,
and then i have some special buttons they are only 1-5 times on all userforms but these buttons should also doing the same on their Userforms (like refresh, change picture from Item, change something else etc.)
I tested this code on a VBA Project on 3 Userforms
Code starting everytime from modAUTOOPEN, Auto_Open
Userforms are:
ALL Userforms have the same code at this time for this test.
frmMain (starting site)
frmOnIt
frmTeM
.
Option Explicit
Private myBtn As clsCMD
Private myBtnColl As Collection
Private Sub UserForm_Activate()
modUI.ufGETICON Me
End Sub
Private Sub UserForm_Initialize()
modMSG.ufINFO
modAUTOOPEN.Workbook_Open Me
Dim ctrl As Control
Set myBtnColl = New Collection
For Each ctrl In Me.Controls
If TypeOf ctrl Is MSForms.CommandButton Then
Set myBtn = New clsCMD
Set myBtn.UserForm = Me
Set myBtn.button = ctrl
myBtnColl.Add myBtn
End If
Next
End Sub
Modules are:
modARCHIV
(not relevant, just old material - maybe its useful in the future)
modAUTOOPEN
(standard stuff)
.
Option Explicit
Public sUSER As String
Public Const sPASS As String = "12345"
Public Sub Workbook_Open(sUSerform As Object)
modUI.ufPOSITION1 sUSerform
End Sub
Public Sub Auto_Open()
' User basierend auf Exceluser ausw?hlen
sUSER = Application.Username
modData.defDEFAULTS
modData.defWORKSHEETS
Load frmMain
frmMain.Show
End Sub
modCHECKS
(not relevant atm, checking which users are using the tool etc.)
modCMD
(where I program all my CMDs for every UF)
.
Option Explicit
Public Sub cmd_Admin()
Dim sAnswer As String
sAnswer = InputBox("Passwort f?r den Zugang zum Adminbereich eingeben:", "Zugang Adminbereich")
If sAnswer = sPASS Then
Unload frmMain
frmMain.Hide
ElseIf sAnswer = "" Then
Exit Sub
Else
MsgBox "Inkorrektes Passwort eingegeben", vbInformation + vbOKOnly, "Passwortabfrage negativ"
End If
Application.Visible = True
End Sub
Public Sub cmd_OItem(sUfName As Object)
Application.ScreenUpdating = False
sUfName.Hide
frmOnIt.Show
End Sub
Public Sub cmd_Test(sUfName As Object)
Application.ScreenUpdating = False
sUfName.Hide
frmTeM.Show
End Sub
modDATA
(standard stuff)
modFUNC
(not relevant atm, for new functions)
modLOAD
(not relevant atm, load all datas to specific UF)
modMSG
(programming and updating all infoboxes on alle UF)
modSAVE
(not relevant atm, save all data from UF to WS or in new WB)
modUI
(checking how many screens and where to open, adding minimize button and windowstaskbar button, etc.)
ClassModules are:
clsCMD (should the connection betweend buttons on UF and modCMD)
.
Option Explicit
Public WithEvents button As MSForms.CommandButton
Private c_Userform As Object
Public Property Set UserForm(ByVal UfName As Object)
Set c_Userform = UfName
End Property
Private Sub Button_click()
CMDTEST UfName, button
End Sub
Public Sub CMDTEST(UfName As Object, button As Object)
Dim sButton As String
Dim sUfName As String
sButton = button.Name
sUfName = c_Userform.Name
If button.Name = "cmd_Admin" Then
modCMD.cmd_Admin
End If
If button.Name = "cmd_OItem" Then
modCMD.cmd_OItem c_Userform
End If
If button.Name = "cmd_Test" Then
modCMD.cmd_Test c_Userform
End If
'If Button.Name = "cmd_Auftragstool" Then
' modCMD.cmd_Auftragstool c_Userform
'End If
'If Button.Name = "cmd_Beenden" Then
' modCMD.cmd_Beenden c_Userform
'End If
End Sub
Let me preface my question with the fact that I am self taught, so please provide as much detail as possible and bear with me if I need you to explain differently or multiple times.
I created a notation/email generating tool for my team using Microsoft Visual Basic 7.0. The only complaint that I received on it was that many of them are not used to hot keys so they depend on using the mouse but right click didn't work. I was able to find code that creates a pop-up for copy and paste when they use right click, and it works great on the few textboxes that are on the main form itself, however it does not work on the majority of the textboxes as they are in a Multipage.
Does anyone know how to alter the below code to work for textboxes on a Multipage? Also, before it is suggested, I did toy with the idea of moving everything out of the Multipage, however that format is the easiest as there are multiple stages and types of notes/emails that they would need to send at any time, so having tabs available for them to simply click is the most user friendly that I was able to create and that they all agreed on.
Thank you all so much in advance!
Code in the form:
Dim cBar As clsBar
Private Sub UserForm_Initialize()
On Error GoTo Whoa
Application.EnableEvents = False
Set cBar = New clsBar
cBar.Initialize Me
Letscontinue:
Application.EnableEvents = True
Exit Sub
Whoa:
MsgBox Err.Description
Resume Letscontinue
End Sub
Code in a Class Module:
Option Explicit
'Popup objects
Private cmdBar As CommandBar
Private WithEvents cmdCopyButton As CommandBarButton
Private WithEvents cmdPasteButton As CommandBarButton
'Useform to use
Private fmUserform As Object
'Control array of textbox
Private colControls As Collection
'Textbox Control
Private WithEvents tbControl As MSForms.TextBox
'Adds all the textbox in the userform to use the popup bar
Sub Initialize(ByVal UF As Object)
Dim Ctl As MSForms.Control
Dim cBar As clsBar
For Each Ctl In UF.Controls
If TypeName(Ctl) = "TextBox" Then
'Check if we have initialized the control array
If colControls Is Nothing Then
Set colControls = New Collection
Set fmUserform = UF
'Create the popup
CreateBar
End If
'Create a new instance of this class for each textbox
Set cBar = New clsBar
cBar.AssignControl Ctl, cmdBar
'Add it to the control array
colControls.Add cBar
End If
Next Ctl
End Sub
Private Sub Class_Terminate()
'Delete the commandbar when the class is destroyed
On Error Resume Next
cmdBar.Delete
End Sub
'Click event of the copy button
Private Sub cmdCopyButton_Click(ByVal Ctrl As Office.CommandBarButton, CancelDefault As Boolean)
fmUserform.ActiveControl.Copy
CancelDefault = True
End Sub
'Click event of the paste button
Private Sub cmdPasteButton_Click(ByVal Ctrl As Office.CommandBarButton, CancelDefault As Boolean)
fmUserform.ActiveControl.Paste
CancelDefault = True
End Sub
'Right click event of each textbox
Private Sub tbControl_MouseUp(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
If Button = 2 And Shift = 0 Then
'Display the popup
cmdBar.ShowPopup
End If
End Sub
Private Sub CreateBar()
Set cmdBar = Application.CommandBars.Add(, msoBarPopup, False, True)
'We’ll use the builtin Copy and Paste controls
Set cmdCopyButton = cmdBar.Controls.Add(ID:=19)
Set cmdPasteButton = cmdBar.Controls.Add(ID:=22)
End Sub
'Assigns the Textbox and the CommandBar to this instance of the class
Sub AssignControl(TB As MSForms.TextBox, Bar As CommandBar)
Set tbControl = TB
Set cmdBar = Bar
End Sub
Get ActiveControl name on a Multipage control
It's necessary to know the multipage's selected Page via a helper function (ActiveControlName) using SelectedItem property and getting the control (its name) from there. Change your button click events as follows:
Relevant button click events in class module clsBar
'Click event of the copy button
Private Sub cmdCopyButton_Click(ByVal Ctrl As Office.CommandBarButton, CancelDefault As Boolean)
Dim sACN As String
sACN = ActiveControlName(fmUserform) ' find control's name
' Debug.Print sACN & ".Copy"
fmUserform.Controls(sACN).Copy ' << instead of fmUserform.ActiveControl.Copy
CancelDefault = True
End Sub
'Click event of the paste button
Private Sub cmdPasteButton_Click(ByVal Ctrl As Office.CommandBarButton, CancelDefault As Boolean)
Dim sACN As String
sACN = ActiveControlName(fmUserform)
' Debug.Print sACN & ".Paste"
fmUserform.Controls(sACN).Paste ' << instead of fmUserform.ActiveControl.Paste
CancelDefault = True
End Sub
Helper function called by above click events
Function ActiveControlName(form As UserForm) As String
'cf Site: https://stackoverflow.com/questions/47745663/get-activecontrol-inside-multipage
'Purpose: get ActiveControl
Dim MyMultiPage As MSForms.MultiPage, myPage As MSForms.Page
If form.ActiveControl Is Nothing Then
' do nothing
ElseIf TypeName(form.ActiveControl) = "MultiPage" Then
Set MyMultiPage = form.ActiveControl
Set myPage = MyMultiPage.SelectedItem
ActiveControlName = myPage.ActiveControl.Name
Else
ActiveControlName = form.ActiveControl.Name
End If
End Function
Side note
Suggest to check for the length of selected text strings in case of empty strings to prevent from unwanted results.
I have created a UserForm in excel 2010 and put 10 toggle button in it.When I run the form all of them can be ON (value = TRUE) but I want only one of them to be ON at the same time.Like below:
In A Class Module
Public WithEvents ToggleGroup As ToggleButton
Private Sub ToggleGroup_click()
' code
End Sub
In a UserForm
Dim Buttons() As New Class1
Private Sub UserForm_Initialize()
Dim ToggleCount As Integer
Dim Ctl As Control
For Each Ctl In UserForm1.Controls
If TypeName(Ctl) = "ToggleButton" Then
ReDim Preserve Buttons(1 To ToggleCount)
Set Buttons(ToggleCount).ToggleGroup = Ctl
End If
Next Ctl
End Sub
In a Module
Sub Form()
UserForm1.Show
End Sub
To use a Toggle button you could try this method:
Create a number of Toggle controls and use the Tag property to group your buttons.
The code below will then compare the name and tag of each control. All toggle buttons with the same tag will be made the opposite of the one that was clicked.
Private Sub Toggle1_Click()
ToggleClick Me.ActiveControl
End Sub
Private Sub Toggle2_Click()
ToggleClick Me.ActiveControl
End Sub
Private Sub Toggle3_Click()
ToggleClick Me.ActiveControl
End Sub
Private Sub Toggle4_Click()
ToggleClick Me.ActiveControl
End Sub
Private Sub ToggleClick(ClickedControl As Control)
Dim Ctl As Control
For Each Ctl In Me.Controls
If TypeName(Ctl) = "ToggleButton" Then
If Ctl.Name <> ClickedControl.Name And Ctl.Tag = ClickedControl.Tag Then
Ctl.Value = Not ClickedControl.Value
End If
End If
Next Ctl
End Sub
Darren's answer works well except for one annoyance: Excel (at least 2016) fires the "_Click" event when you set the value of the toggle control. Annoying and not obvious (I'd go so far as to call it "errata" if not an outright bug), so I'd make the following additions:
Add the line If Me.ToggleControlName.Value = False then Exit Sub as the first line of each "_Click" event handler.
Add the condition And Ctl.Value = True to the ToggleClick subroutine's IF statement to prevent extra firings of the "_Click" event that aren't actually changing a toggle's value (if it's False, no need to set it to False, firing a useless _Click event handler).
I couldn't get Darren's answer to work even with Erik's modification. The below line kept throwing an error.
Ctl.Value = Not ClickedControl.Value
Below is the likely dumbed down version that worked for me for a simple system of 3 toggles.
Private Sub ToggleButton1_Click()
If Me.ToggleButton1.Value = False Then Exit Sub
Me.ToggleButton2.Value = False
Me.ToggleButton3.Value = False
End Sub
Private Sub ToggleButton2_Click()
If Me.ToggleButton2.Value = False Then Exit Sub
Me.ToggleButton1.Value = False
Me.ToggleButton3.Value = False
End Sub
Private Sub ToggleButton3_Click()
If Me.ToggleButton3.Value = False Then Exit Sub
Me.ToggleButton1.Value = False
Me.ToggleButton2.Value = False
End Sub
The only down side to this is that I can toggle off the currently active button so that none are active. I would like it so that if you try to toggle off the active one, it stays active. So one button is always on.
In the Userform:
Dim Buttons() As New Class1
Private Sub UserForm_Initialize()
Dim ToggleCount As Integer
Dim Ctl As Control
For Each Ctl In UserForm1.Controls
If TypeName(Ctl) = "ToggleButton" Then
ToggleCount = ToggleCount + 1
ReDim Preserve Buttons(1 To ToggleCount)
Set Buttons(ToggleCount).ToggleGroup = Ctl
Buttons(ToggleCount).CtlName = Ctl.Name
End If
Next Ctl
End Sub
In the Class Module:
Public WithEvents ToggleGroup As ToggleButton
Public CtlName As String
Private Sub ToggleGroup_click()
' code
End Sub
Private Sub ToggleGroup_MouseUp(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
Dim Ctl As Control
For Each Ctl In UserForm1.Controls
If TypeName(Ctl) = "ToggleButton" Then
If Not Ctl.Name = CtlName Then
Ctl.Value = False
End If
End If
Next Ctl
End Sub
'Try this in the Userform.
Private Sub ToggleButton1_Click()
If Me.ToggleButton1.Value = True Then
Me.ToggleButton2.Value = Not (Me.ToggleButton1.Value)
Else
Me.ToggleButton1.Value = Not (Me.ToggleButton2.Value)
End Sub
Private Sub ToggleButton2_Click()
If Me.ToggleButton2.Value = True Then
Me.ToggleButton1.Value = Not (Me.ToggleButton2.Value)
Else
Me.ToggleButton2.Value = Not (Me.ToggleButton1.Value)
End If
End Sub
'Works flawlesly for me.
'Cheers!
i have a macro (Makro1) that is assigned to a button in a custom toolbar (Custom1) with caption "Schutzstatus". i want the toolbar only to be loaded with this very xls-file.
can someone help me out with the code?
i managed to customize the tooltip:
Application.CommandBars("Custom1").Controls(1).TooltipText = "Abfrage des Schutzstatus der Arten im Zwischenspeicher"
but i fail in creating the whole thing by vba..
thanks in advance,
kay
You don't actually need to (re)create the whole toolbar on loading your XLS, but you need to display/hide it during certain navigations
1 create the toolbar
2 attach it to your XLS (view / toolbars / customize .... / attach)
3 create event procedures to show/hide your toolbar; unless you want to have a specific behaviour for different sheets, the following should be enough to care for all navigation:
Private Sub Workbook_Activate()
' show toolbar
Application.CommandBars("CoolBar").Visible = True
Application.CommandBars("CoolBar").Controls(1).TooltipText = "C'mon squeeze me"
End Sub
Private Sub Workbook_BeforeClose(Cancel As Boolean)
' drop toolbar
Application.CommandBars("CoolBar").Delete
End Sub
Private Sub Workbook_Deactivate()
' see if we have a toolbar (it might have been already deleted by "Workbook_BeforeClose"
' if yes - hide it
Dim Idx As Integer
For Idx = 1 To Application.CommandBars.Count
If Application.CommandBars(Idx).Name = "CoolBar" Then
Application.CommandBars("CoolBar").Visible = False
End If
Next Idx
End Sub
Private Sub Workbook_SheetActivate(ByVal Sh As Object)
' display toolbar
Application.CommandBars("CoolBar").Visible = True
End Sub
Private Sub Workbook_SheetDeactivate(ByVal Sh As Object)
Application.CommandBars("CoolBar").Visible = False
End Sub
Place all in the "ThisWorkbook" object - so they fire on all sheets.
4 After saving the toolbar with the XLS and testing, close the XLS - the toolbar will be still present in your application object - and delete the toolbar from there. Don't panic, it's coming back when you re-open your XLS file.
Hope this helps
Tschüss MikeD
Actually the answer was close but didn't work for me. That .Delete does delete the command bar completely as confirmed by Kay in his last comment. You basically had to recreate but bar and button again when the workbook is opened. Below is the improved code:
Private Sub Workbook_Activate()
' show toolbar
Dim SortBar As CommandBar
Dim BarControl As CommandBarControl
Set SortBar = FindCommandBar("SortBar")
If SortBar Is Nothing Then
Set SortBar = Application.CommandBars.Add("SortBar")
Set BarControl = SortBar.Controls.Add
BarControl.OnAction = "Your_Macro_Name"
BarControl.Caption = "Text for your button"
BarControl.Style = msoButtonCaption
End If
SortBar.Visible = True
End Sub
Private Sub Workbook_BeforeClose(Cancel As Boolean)
' drop toolbar
Application.CommandBars("SortBar").Delete
End Sub
Private Sub Workbook_Deactivate()
' see if we have a toolbar (it might have been already deleted by "Workbook_BeforeClose"
' if yes - hide it
Dim SortBar As CommandBar
Set SortBar = FindCommandBar("SortBar")
If Not SortBar Is Nothing Then
SortBar.Visible = False
End If
End Sub
Private Function FindCommandBar(Name As String) As CommandBar
Dim Idx As Integer
For Idx = 1 To Application.CommandBars.Count
Set FindCommandBar = Application.CommandBars(Idx)
If FindCommandBar.Name = Name Then
Exit Function
End If
Next Idx
Set FindCommandBar = Nothing
End Function
Private Sub Workbook_SheetActivate(ByVal Sh As Object)
' display toolbar
Application.CommandBars("SortBar").Visible = True
End Sub
Private Sub Workbook_SheetDeactivate(ByVal Sh As Object)
Application.CommandBars("SortBar").Visible = False
End Sub