PDA

View Full Version : [SOLVED:] #Const



gmaxey
05-26-2014, 11:07 PM
I'm working on a project that I would like to use with multiple versions of Word 2007/2010/2013.

Word 2013 has a few new features that I want to incorporate, but doing so causes compile errors when I try to use the project in Word 2007 or 2010. I've figured out how to avoid that by using a conditional compilation statement:

#Const Version = 15#

Will let the code run only if I'm using Word 2013. The problem (question) is to use the tool in Word 2010 I first have to open the project and change to:

#Const Version = 14#

That just seems clunky and I'm hoping there is a better way? It would sure be nice if I could just:
#Const Version = Application.Version

but that won't work.

Thanks

macropod
05-27-2014, 02:12 AM
Other than testing the VBA version, anything else (e.g. testing the application version) is liable to lead to compile-time errors.

#If VBA7 Then
MsgBox "VBA Version 7"
#ElseIf VBA6 Then
MsgBox "VBA Version 6"
#Else
MsgBox "VBA Version 5"
#End If
The #IF directive will correctly handle Properties and Methods that produce compile time errors.

gmaxey
05-27-2014, 04:44 AM
Paul,

Yes, I'm aware how #If..#Else..#End if works. Unfortunately both Word 2010 and 2013 use VBA7. I guess there is simply no way to distinguish between the two at compile time :-(

Thanks.

ranman256
05-27-2014, 05:52 AM
No need for the #.

Paul_Hossler
05-27-2014, 10:19 AM
No need for the #.

The second # of course

@greg

I usually use the Project Properties for that. Not perfect, but possibly an option

Bob Phillips
05-27-2014, 10:27 AM
If you have trusted access you could always have some code that triggers on open that tests the application version and update the code dynamically.

Bob Phillips
05-27-2014, 11:38 AM
Here is an example of what I mean (this is Excel, should be modifiable)


Option Explicit

Const vbext_ct_StdModule As Long = 1
Const vbext_ct_ClassModule As Long = 2
Const vbext_ct_MSForm As Long = 3

Private Sub Workbook_Open() '<<<<<<<< change this to whatever fires on Word document open
Dim VBProject As Object
Dim VBMod As Object
Dim mStartLine As Long
Dim mLine As String
Dim mModuleDone As Boolean

Set VBProject = Application.VBE.ActiveVBProject

If Not VBAIsTrusted(VBProject) Then

MsgBox "You need trusted access", vbOKOnly, "Conditionals"
Else

If VBProject Is ThisWorkbook.VBProject Then '<<<< change ThisWorkbook to ThisDocument

With VBProject

For Each VBMod In .VBComponents

If VBMod.Type = vbext_ct_ClassModule Or VBMod.Type = vbext_ct_MSForm Or VBMod.Type = vbext_ct_StdModule Then

With VBMod.codemodule

mStartLine = 1
mModuleDone = False
Do Until mModuleDone

mModuleDone = mStartLine > .CountOfLines
If Not mModuleDone Then

mLine = .Lines(mStartLine, 1)
If mLine Like "*Const Version = *" Then

.DeleteLines mStartLine, 1
End If

mStartLine = mStartLine + 1
End If
Loop

'insert a conditional compilation line
.InsertLines .CountOfDeclarationLines + 1, "#Const Version = " & Val(Application.Version)
End With
End If
Next VBMod
End With
End If
End If
End Sub

'-----------------------------------------------------------------
Private Function VBAIsTrusted(ByRef Project As Object) As Boolean
'-----------------------------------------------------------------
Dim mpVBC As Object
Dim mpAlerts As Boolean
mpAlerts = Application.DisplayAlerts
Application.DisplayAlerts = False
On Error Resume Next
Set mpVBC = Project.VBComponents.Item(1)
On Error GoTo 0
Application.DisplayAlerts = mpAlerts
VBAIsTrusted = Not mpVBC Is Nothing
End Function

gmaxey
05-27-2014, 12:18 PM
All,

Sorry for be slow to get back. Thanks for the replies.

xld, good idea, but the trouble is that user would have to leave trusted access on right? Otherwise each time the tool is used they would have to trust access. I don't like the idea of having to manually change the #Const either in the module or the project as Paul suggests, but that may be the least annoyance. Once it is done it is done.

Bob Phillips
05-27-2014, 01:16 PM
xld, good idea, but the trouble is that user would have to leave trusted access on right?

Or you could put it in a trusted location.

gmaxey
05-27-2014, 05:48 PM
xld,

I like you method and it would be great if I can just get it work! The code does what I need it to do when it works, but when it works and when it doesn't is strange.

Here is what is happening. I have "Trust Access to VBA project object model" set in both Word 2010 and 2013. My file is in a trusted location. The code is set to run in and AutoOpen() macro.

Here is what happens.

In Word 2010, I open the file and I get "You need trusted access." I open the VBE and run the code and it works perfectly.

I close the file in Word 2010 and open it in Word 2013 and I get no message but nothing happens. I open the VBE and run the code and again it runs perfectly.

Then I went back to Word 2010 and opened the file and got the same trusted access message. I closed and reopened the file and I got no message and the code ran.


I then went back to Word 2013 and same thing. Open the file once and nothing, close and open a second time and an it works

Any ideas?

macropod
05-27-2014, 06:19 PM
In Word 2010, when I open the file and I get a Runtime Error 6068, not your message. I suspect the difference in behaviour may be due to you running 2010 and 2013 in the same environment (I don't have 2013 installed). Try:

On Error Resume Next
Set VBProject = Application.VBE.ActiveVBProject
On Error GoTo 0
If VBProject Is Nothing Then
MsgBox "You need trusted access", vbOKOnly, "Conditionals"
Else
That should at least ensure your users get your error message.

Also, instead of putting your code into the auto-open sub, insert it into a different Module. Then you can use an Application.Version test to call the code in whichever module is applicable to the Word version you're using. That would obviate the need for trusted access and everything that goes with it. Your userform could likewise use Application.Version tests to determine which module to call subs/functions from, according to the Word version you're using.

Bob Phillips
05-27-2014, 11:59 PM
Greg,

I opened that file in Word 2010 and it worked fine, got the message Bingo and nothing else. I then opened it in Word 2013, and same thing. Both versions had the "Trust Access to VBA project object model" box checked.

gmaxey
05-28-2014, 02:56 AM
xld, Well I'm just baffled. I have Word 2003, 2007. 2010, and 2013 installed. 2010 is the default. Here when I open either 2010 or 2013 and open the file nothing happens the first time, but after that it works fine repeatedly until I close Word. When I open either version of Word again it is back to a single false start then all works.

gmaxey
05-28-2014, 02:59 AM
Paul,

Still getting odd results. The project involves content controls and just a few instances where Word 2013 has properties/methods of the control that Word 2013 doesn't. All of the code is in the same module (userform). The #IF .. #End works well. If I can't get the dynamic process that xld offered to work, I'll just put out two versions with the correct #CONST Version.

Thanks.

Bob Phillips
05-28-2014, 04:42 AM
Greg,

If the form has those controls regardless of version, you could do what Paul suggests and have two modules, one for 2010 and one for 2013 and have subs in each that processes the control, that is pass the whole control object byref to that sub. I haven't used this technique in quite a while, but it is what I used to do to emulate Addressof when using Excel 97 and Excel 2000. I found an old example that I posted here (http://www.pcreview.co.uk/forums/vbulletin-code-creating-count-down-timer-stopwatch-t1877188.html)

gmaxey
05-28-2014, 05:08 AM
xld,
Yes, that is an idea. Thanks (you too Paul).

Frosty
05-29-2014, 02:05 PM
Not a huge fan of the above approach of actually modifying the project code upon opening... why do you need to differentiate between Word 2007 and Word2010 at compile time? What are the compile errors you get in Word 2007 which don't occur in Word 2010?

It seems like you could use conditional logic for VBA7 (to differentiate for 2013 compile issues), and then simply test for Application.Version within a Word 2010/Word 2007 logic block. I haven't programmed for Office 2013 yet, but I do have a project which I need to be compatible with both 2007 and 2010, and Application.Version has worked fine for me. And I've used conditional compile for when code chunks need to work in Word 2003 (although obviously I would then need to save the project down to a .dot file).

Frosty
05-29-2014, 02:09 PM
Sorry, it looks like the questions may have been answered already... but I agree with having different modules. Word only compiles modules only as that code is called, so if you know you have a module which won't compile in a specific version... it's okay, as long as you don't call any subroutines from there. And if you really need to have it work... remember you can pass items as objects instead of the "real" thing, and then the properties will be available in the version that they're available in, and cause run-time errors in the versions that they're not available in (but no compile errors).

Bob Phillips
05-29-2014, 04:00 PM
I think we already said all of that!

gmaxey
05-29-2014, 09:50 PM
Jason/xld,

I was being dense and unless I missed it previously, it is the practice of "passing items as objects instead of the "real" thing" that I should have done in the first place. I've done that before when working with content controls between Word2010 and Word2007 (there is no checkbox control in Word2007) and I simply forgot or lost the tree in the forest.

That is exactly what I've done and using that practice with Val(Application.Version) I'm able to run the code in all three versions of Word without issue.

Thanks for all of the responses (Paul and Paul2 and Ranman also) and interest in my post!