How to programmatically change conditional compilation properties of a VBA project How to programmatically change conditional compilation properties of a VBA project vba vba

How to programmatically change conditional compilation properties of a VBA project


Inspired by this approach, shown by SiddharthRout, I managed to find the following solution using SendMessage and FindWindow:

Option ExplicitPrivate Declare Function FindWindow Lib "user32" Alias "FindWindowA" _(ByVal lpClassName As String, ByVal lpWindowName As String) As LongPrivate Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" _(ByVal hWnd1 As Long, ByVal hWnd2 As Long, ByVal lpsz1 As String, _ByVal lpsz2 As String) As LongPrivate Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" _(ByVal hwnd As Long, ByVal lpString As String, ByVal cch As Long) As LongPrivate Declare Function GetWindowTextLength Lib "user32" Alias _"GetWindowTextLengthA" (ByVal hwnd As Long) As LongPrivate Declare Function SendMessage Lib "user32" Alias "SendMessageA" _(ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As LongConst WM_SETTEXT = &HCConst BM_CLICK = &HF5Public Sub subSetconditionalCompilationArguments()    Dim strArgument As String    Dim xlApp As Object    Dim wbTarget As Object    Dim lngHWnd As Long, lngHDialog As Long    Dim lngHEdit As Long, lngHButton As Long    strArgument = "PACKAGE_1 = 1"    Set xlApp = CreateObject("Excel.Application")    xlApp.Visible = False    Set wbTarget = xlApp.Workbooks.Open("C:\Temp\Sample.xlsb")    'Launch the VBA Project Properties Dialog    xlApp.VBE.CommandBars(1).FindControl(ID:=2578, recursive:=True).Execute    'Get the handle of the "VBAProject" Window    lngHWnd = FindWindow("#32770", vbNullString)    If lngHWnd = 0 Then        MsgBox "VBAProject Property Window not found!"        GoTo Finalize    End If    'Get the handle of the dialog    lngHDialog = FindWindowEx(lngHWnd, ByVal 0&, "#32770", vbNullString)    If lngHDialog = 0 Then        MsgBox "VBAProject Property Window could not be accessed!"        GoTo Finalize    End If    'Get the handle of the 5th edit box    lngHEdit = fctLngGetHandle("Edit", lngHDialog, 5)    If lngHEdit = 0 Then        MsgBox "Conditional Compilation Arguments box could not be accessed!"        GoTo Finalize    End If    'Enter new argument    SendMessage lngHEdit, WM_SETTEXT, False, ByVal strArgument    DoEvents    'Get the handle of the second button box (=OK button)    lngHButton = fctLngGetHandle("Button", lngHWnd)    If lngHButton = 0 Then        MsgBox "Could not find OK button!"        GoTo Finalize    End If    'Click the OK Button    SendMessage lngHButton, BM_CLICK, 0, vbNullStringFinalize:    xlApp.Visible = True    'Potentially save the file and close the app hereEnd SubPrivate Function fctLngGetHandle(strClass As String, lngHParent As Long, _    Optional Nth As Integer = 1) As Long    Dim lngHandle As Long    Dim i As Integer    lngHandle = FindWindowEx(lngHParent, ByVal 0&, strClass, vbNullString)    If Nth = 1 Then GoTo Finalize    For i = 2 To Nth        lngHandle = FindWindowEx(lngHParent, lngHandle, strClass, vbNullString)    NextFinalize:    fctLngGetHandle = lngHandleEnd Function


For Access 2000 I used:

Application.GetOption("Conditional Compilation Arguments")

for getting,

Application.SetOption("Conditional Compilation Arguments", "<arguments>")

for setting.

That's all.


The only way to affect anything in that dialog box is through SendMessage API functions, or maybe Application.SendKeys. You'd be better off declaring the constants in code, like this:

#Const PACKAGE_1 = 0

And then have your code modify the CodeModule of all your VBA components:

Dim comp As VBComponentFor Each comp In ThisWorkbook.VBProject.VBComponents    With comp.CodeModule        Dim i As Long        For i = 1 To .CountOfLines            If Left$(.Lines(i, 1), 18) = "#Const PACKAGE_1 =" Then                .ReplaceLine i, "#Const PACKAGE_1 = 1"            End If        Next i    End WithNext comp