Prevent VBA editor from being opened

Michael M

Well-known Member
Joined
Oct 27, 2005
Messages
21,898
Office Version
  1. 365
  2. 2019
  3. 2013
  4. 2007
Platform
  1. Windows
Hi All
A colleague that I have written a workbook for has an issue with one of the users trying to open the VBA editor and see the code.
So it got me to thinking....is there a way to close the workbook if the VBE is opened.
I was thinking along the lines of when the press ALT + F11 a msgbox tells them they are unauthorised to view this page, and then closes the workbook without saving.

I haven't seen this done anywhere before, so it is a curiosity question at the moment.
The project in question does have a VBA password at the moment, so it's not a major problem yet !!

Any suggestions / inputs appreciated.
 

Excel Facts

Convert text numbers to real numbers
Select a column containing text numbers. Press Alt+D E F to quickly convert text to numbers. Faster than "Convert to Number"
That is not a robust solution.

the suggested workaround will only work when attempting to open the VBE by pressing ALT+F11 . It will not work when accessing the VBE from the VIEW CODE on the main menu or from the right click menu of a sheet tab or when adding a control to a sheet or when opened via code etc...

Here is a solution I suggest to make sure the VBE is never opened while the workbook is loaded no matter which venue .


Add a new standard module to the project and put this code in it :

Code:
Option Explicit
 
Private Declare Function FindWindow Lib "user32.dll" _
Alias "FindWindowA" _
(ByVal lpClassName As String, _
ByVal lpWindowName As String) As Long

Private Declare Function GetWindowLong Lib "user32" _
Alias "GetWindowLongA" ( _
ByVal hwnd As Long, _
ByVal nIndex As Long) As Long
 
Private Declare Function SetWindowsHookEx Lib "user32" _
Alias "SetWindowsHookExA" _
(ByVal idHook As Long, _
ByVal lpfn As Long, _
ByVal hmod As Long, _
ByVal dwThreadId As Long) As Long
 
Private Declare Function CallNextHookEx Lib "user32" _
(ByVal hHook As Long, _
ByVal nCode As Long, _
ByVal wParam As Long, _
lParam As Any) As Long
 
Private Declare Function UnhookWindowsHookEx Lib "user32" _
(ByVal hHook As Long) As Long
 
Private Declare Function GetCurrentThreadId Lib "kernel32" _
() As Long
 
Private Declare Function GetClassName Lib "user32.dll" _
Alias "GetClassNameA" _
(ByVal hwnd As Long, _
ByVal lpClassName As String, _
ByVal nMaxCount As Long) As Long

Public Declare Function SetParent Lib "user32.dll" _
(ByVal hWndChild As Long, _
ByVal hWndNewParent As Long) As Long

Private Declare Function GetDesktopWindow Lib "user32.dll" _
() As Long

Private Declare Function LockWindowUpdate Lib "user32.dll" _
(ByVal hwndLock As Long) As Long

Private Declare Function ShowWindow Lib "user32.dll" _
(ByVal hwnd As Long, _
ByVal nCmdShow As Long) As Long


Private Const GWL_HINSTANCE As Long = (-6)
Private Const WH_CBT As Long = 5
Private Const HCBT_ACTIVATE As Long = 5

Private lCBTHook  As Long
Private lVBEhwnd As Long


Public Sub Hide_The_VBE_Window()

    Application.SendKeys "%{F11}"

    lCBTHook = SetWindowsHookEx(WH_CBT, AddressOf CBTProc, _
    GetAppInstance, GetCurrentThreadId)
    
End Sub


Public Sub Restore_The_VBE_Window()

    LockWindowUpdate GetDesktopWindow
    ShowWindow lVBEhwnd, 0
    SetParent lVBEhwnd, 0
    ShowWindow lVBEhwnd, 3
    ShowWindow lVBEhwnd, 0
    LockWindowUpdate 0
    
End Sub



Private Function CBTProc _
(ByVal idHook As Long, ByVal wParam As Long, _
ByVal lParam As Long) As Long
 
    Dim sBuffer As String
    Dim lRetVal As Long
    Dim hParentWnd As Long
 
    'Lock the screen.
    LockWindowUpdate GetDesktopWindow
    
    Select Case idHook
        Case Is = HCBT_ACTIVATE 'A window has been activated
            'Is it the VBE window ?
            sBuffer = Space(256)
            lRetVal = GetClassName(wParam, sBuffer, 256)
            If Left(sBuffer, lRetVal) = "wndclass_desked_gsk" Then
                'It's our VBE window so remove the CBT hook now.
                UnhookWindowsHookEx lCBTHook
                'Hide the VBE window.
                ShowWindow wParam, 0
                'Store the VBE hwnd for restoring it later.
                lVBEhwnd = wParam
                'Retrieve the XL process 'Thunder' window.
                hParentWnd = FindWindow("ThunderMain", vbNullString)
                If hParentWnd Then
                    'Make the VBE window the child of the Thunder
                    'window to remain invisible.
                    SetParent wParam, hParentWnd
                End If
            End If
    End Select
    
    'Unlock the screen.
     LockWindowUpdate 0
 
    CBTProc = CallNextHookEx _
    (lCBTHook, idHook, ByVal wParam, ByVal lParam)
 
End Function


Private Function GetAppInstance() As Long
 
    GetAppInstance = GetWindowLong _
    (FindWindow("XLMAIN", Application.Caption), GWL_HINSTANCE)
 
End Function
This code goes in the Workbook module :

Code:
Option Explicit

Private Sub Workbook_Open()
    Call Hide_The_VBE_Window
End Sub

Private Sub Workbook_BeforeClose(Cancel As Boolean)
    Call Restore_The_VBE_Window
End Sub
 
Upvote 0
Surely he'd just disable macros, then view the code?
 
Upvote 0
Surely he'd just disable macros, then view the code?

Hi Rorya.

Yes, this relies on Macros being enabled. Locking the project is obviously the solution. As pointed out by the OP this is more of a curiosity than anything.

However there is a useful use of blocking access to the VBE and that is when running an API timer procedure or any other API callback function which would almost certainly crash the whole application if the user were to accidently reset the Project . Sometimes just activating the VBE main window can be problematic specially when using a windows hook or subclassing a window. I have used this safety trick before successfully.
 
Upvote 0
Hi Jaafar and Rory
I'm fully aware of the "Surely he'd just disable macros", so have locked the Project anyway.
But I was looking for something different, simply to throw the clients user off a little.
I have a "worksheet very hidden" code to force the users to enable macros, and I'm actually surprised at the number of users that don't know about the SHIFT key option either. Also, can you imagine the surprise when they get a InputBox for a password to open ALT + F11....it's quite funny, if not for the novelty value alone !!!
Anyway, I appreciate both of your inputs and also the extra code from Jaafar.
Thanks to you both.
 
Upvote 0
That is not a robust solution.

the suggested workaround will only work when attempting to open the VBE by pressing ALT+F11 . It will not work when accessing the VBE from the VIEW CODE on the main menu or from the right click menu of a sheet tab or when adding a control to a sheet or when opened via code etc...

Here is a solution I suggest to make sure the VBE is never opened while the workbook is loaded no matter which venue .


Add a new standard module to the project and put this code in it :

Code:
Option Explicit
 
Private Declare Function FindWindow Lib "user32.dll" _
Alias "FindWindowA" _
(ByVal lpClassName As String, _
ByVal lpWindowName As String) As Long

Private Declare Function GetWindowLong Lib "user32" _
Alias "GetWindowLongA" ( _
ByVal hwnd As Long, _
ByVal nIndex As Long) As Long
 
Private Declare Function SetWindowsHookEx Lib "user32" _
Alias "SetWindowsHookExA" _
(ByVal idHook As Long, _
ByVal lpfn As Long, _
ByVal hmod As Long, _
ByVal dwThreadId As Long) As Long
 
Private Declare Function CallNextHookEx Lib "user32" _
(ByVal hHook As Long, _
ByVal nCode As Long, _
ByVal wParam As Long, _
lParam As Any) As Long
 
Private Declare Function UnhookWindowsHookEx Lib "user32" _
(ByVal hHook As Long) As Long
 
Private Declare Function GetCurrentThreadId Lib "kernel32" _
() As Long
 
Private Declare Function GetClassName Lib "user32.dll" _
Alias "GetClassNameA" _
(ByVal hwnd As Long, _
ByVal lpClassName As String, _
ByVal nMaxCount As Long) As Long

Public Declare Function SetParent Lib "user32.dll" _
(ByVal hWndChild As Long, _
ByVal hWndNewParent As Long) As Long

Private Declare Function GetDesktopWindow Lib "user32.dll" _
() As Long

Private Declare Function LockWindowUpdate Lib "user32.dll" _
(ByVal hwndLock As Long) As Long

Private Declare Function ShowWindow Lib "user32.dll" _
(ByVal hwnd As Long, _
ByVal nCmdShow As Long) As Long


Private Const GWL_HINSTANCE As Long = (-6)
Private Const WH_CBT As Long = 5
Private Const HCBT_ACTIVATE As Long = 5

Private lCBTHook  As Long
Private lVBEhwnd As Long


Public Sub Hide_The_VBE_Window()

    Application.SendKeys "%{F11}"

    lCBTHook = SetWindowsHookEx(WH_CBT, AddressOf CBTProc, _
    GetAppInstance, GetCurrentThreadId)
   
End Sub


Public Sub Restore_The_VBE_Window()

    LockWindowUpdate GetDesktopWindow
    ShowWindow lVBEhwnd, 0
    SetParent lVBEhwnd, 0
    ShowWindow lVBEhwnd, 3
    ShowWindow lVBEhwnd, 0
    LockWindowUpdate 0
   
End Sub



Private Function CBTProc _
(ByVal idHook As Long, ByVal wParam As Long, _
ByVal lParam As Long) As Long
 
    Dim sBuffer As String
    Dim lRetVal As Long
    Dim hParentWnd As Long
 
    'Lock the screen.
    LockWindowUpdate GetDesktopWindow
   
    Select Case idHook
        Case Is = HCBT_ACTIVATE 'A window has been activated
            'Is it the VBE window ?
            sBuffer = Space(256)
            lRetVal = GetClassName(wParam, sBuffer, 256)
            If Left(sBuffer, lRetVal) = "wndclass_desked_gsk" Then
                'It's our VBE window so remove the CBT hook now.
                UnhookWindowsHookEx lCBTHook
                'Hide the VBE window.
                ShowWindow wParam, 0
                'Store the VBE hwnd for restoring it later.
                lVBEhwnd = wParam
                'Retrieve the XL process 'Thunder' window.
                hParentWnd = FindWindow("ThunderMain", vbNullString)
                If hParentWnd Then
                    'Make the VBE window the child of the Thunder
                    'window to remain invisible.
                    SetParent wParam, hParentWnd
                End If
            End If
    End Select
   
    'Unlock the screen.
     LockWindowUpdate 0
 
    CBTProc = CallNextHookEx _
    (lCBTHook, idHook, ByVal wParam, ByVal lParam)
 
End Function


Private Function GetAppInstance() As Long
 
    GetAppInstance = GetWindowLong _
    (FindWindow("XLMAIN", Application.Caption), GWL_HINSTANCE)
 
End Function
This code goes in the Workbook module :

Code:
Option Explicit

Private Sub Workbook_Open()
    Call Hide_The_VBE_Window
End Sub

Private Sub Workbook_BeforeClose(Cancel As Boolean)
    Call Restore_The_VBE_Window
End Sub
It’s not work on 64 bit office you can convert it to 64 bit ?
 
Upvote 0
It’s not work on 64 bit office you can convert it to 64 bit ?,,,,,can anyone post with the code that work on 64 bit office version
 
Upvote 0

Forum statistics

Threads
1,224,823
Messages
6,181,183
Members
453,020
Latest member
Mohamed Magdi Tawfiq Emam

We've detected that you are using an adblocker.

We have a great community of people providing Excel help here, but the hosting costs are enormous. You can help keep this site running by allowing ads on MrExcel.com.
Allow Ads at MrExcel

Which adblocker are you using?

Disable AdBlock

Follow these easy steps to disable AdBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the icon in the browser’s toolbar.
2)Click on the "Pause on this site" option.
Go back

Disable AdBlock Plus

Follow these easy steps to disable AdBlock Plus

1)Click on the icon in the browser’s toolbar.
2)Click on the toggle to disable it for "mrexcel.com".
Go back

Disable uBlock Origin

Follow these easy steps to disable uBlock Origin

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back

Disable uBlock

Follow these easy steps to disable uBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back
Back
Top