Compile errors when supporting 2003,2007,2010

Started by paulv45, September 13, 2010, 11:58:04 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

paulv45

My application delivers VBA code in a stencil.  I would like to deliver a single stencil that supports 2003, 2007, 2010.  To do this there must be clean compiles on all versions.  I can almost do that, but am stuck when it comes to connecting to the ribbon.

To do this I use the line:
Implements IRibbonExtensibility
in the class defining the connection to the ribbon.  This compiles in 2007 and 2010 but fails with need user defined type message in 2003.

A way that I think will works is to use:
Conditional Compilation Arguments:
cc2003 = 1 for 2003 and cc2003 = 0 for all else

In code:


' In some module:

Option Explicit

#If cc2003 Then
   Type IRibbonExtensibility
       dummy1 As Integer
   End Type
#End If

' In Class Ribbon:

Option Explicit

#If cc2003 Then
#Else
   Implements IRibbonExtensibility
#End If


As far as I can tell, using this technique means that I have to create 2 versions of the stencil, one for 2003 and the other for 2007, 2010.  Then sort out at install or run time which version to use.

I would prefer a single stencil that supports all versions.
Anyone have any ideas I could try?
Thanks, Paul

Visio Guy

VBA is good at "late binding". I wonder if you do a bunch of "object" code that is late-bound if Visio happens to support it?

Instead of explicitly declaring variables of types that Visio 2003 doesn't know about, you just create Object or Variant variables. You don't get the intellisense drop-downs to help you in coding, but it won't crash when the stencil opens.

You could then check Visio.Application.Version to decide which routines to call.

Here's an example that compares the two methods:


Option Explicit

Sub Explicit()

  Dim shp As Visio.Shape
  Set shp = Visio.ActivePage.DrawRectangle(0, 0, 2, 2)
  shp.Text = "Explicit"
 
End Sub

Sub LateBound()

  Dim shp
  Set shp = Visio.ActivePage.DrawRectangle(0, 0, 2, 2)
  shp.Text = "LateBound" '...no intellisense for shp.Text
 
End Sub
For articles, tips and free content, see the Visio Guy Website at http://www.visguy.com
Get my Visio Book! Using Microsoft Visio 2010

paulv45

Thanks for looking at this, Chris.  If I get your drift I should be able to leave out the "Implements IRibbonExtensibility" specification entirely as long as the class being defined has the appropriate methods defined.  Indeed with I do this compile is clean, but I get a runtime error "Invalid Parameter" when doing the vsoApplication.RegisterRibbonX call.  Somehow runtime processing seems to know that the pointer is to a class not specifically identified as implementing IRibbonExtensibility.  I experimented some with trying to define some arbitrary interface class to see if "Interface" does something magic, but was not successful. -- Paul

Nikolay

#3
Hi Paul,
I think a class can either implement an interface, or not, but you can't actually "conditionally" comment this out, can you..? I don't think VBA allows tricks like that.
So if you want to implement IRibbonExtensibility, you'll need a different stencil for v2003 (because this interface was firstly introduced in Office 2007 type library).

Please keep in mind that if all you need is a ribbon in Visio 2010, and a button in previous versions, you can do that without implementing IRibbonExtensibility, or calling RegisterRibbonX at all.
As far as I understand, these are targeted for Addins/("legacy" Addons in case of RegisterRibbonX?), not VBA code. For VBA, you could try Document.CustomUI proeprty.
This property allows binding a Ribbon user interface to a Viosio document/stencil without writing a line of code!

I've attached an example drawing that adds a button to Visio 2003, 2007 standard toolbar and a ribbon button to Visio 2010 (it uses VBA only).
When user clicks this button, message "Hello world" is shown.

paulv45

Thanks for working on this, Nikolay, and for the nice concise example.

Your conclusions support where I was leaning -- use Document.CustomUI.
There are two downsides that I know of to that approach.
1.  You need a save-close-reopen cycle each time you change the ribbon.
2.  If, as in my case, the ribbon is in a stencil but associated with each drawing (i.e. the template for your drawings) you need to define a reference from the drawing to the stencil with the ugly side effects of needing at least one line of dummy code in the drawing for the reference to stick through a save-close-reopen cycle and then to be signed to leap the security hoops.

With regard to conditional compile -- the code in my initial post actually works, but it's not a run time conditional.  It is set in the project properties.  Also the conditional around "Implements" doesn't prevent the 2003 compile error by the one defining the User Defined Type tricks the 2003 compiler to think Interface points to something.  This takes you to the same place you ended up -- need two different stencils.  In my example the stencils are identical from a code point of view but one compiled with each setting of the compile condition.  Then you play games at install or run time which to use.

Bottom line so far -- no way to bypass the 2003 compile error on undefined Interface -- pick your poison on using Register or CustomUI.

Paul

Nikolay

Hi Paul,
1. Yes, unfortunately AFAIK you have to save-close-reopen on each change... But do you change the user interface that often..?
2. Yes it seems to be an issue when code is located in a stencil... You can't refer to a stencil from "OnAction" attribute. Right. Maybe you could consider providing a template..?
Anyways, I've got nothing better to offer ;)

AndyW

It's a shame Microsoft seem to ignore the effects that user interface changes can have. It matters not whether the ribbon approach is better or not. If the new version is not 100% backward compatible we can be forced into supporting different versions of applications. Like you my application works fine with 2003/2007, but now looking at having to maintain a different version just because of these ribbon changes, plus a whole lot of unplanned development to support it.
Live life with an open mind

paulv45

Hi Nikolay and Andy -- Thanks for interest in beating through this issue.

Nikolay 1 -- While it's true the UI doesn't change much, save-close-reopen is a real pain during UI development, but can deal with it.  It's particularly painful in the code-in-stencil model since there needs to be a reference from the drawing to the stencil and that reference blocks the close.  I have worked around that using a two drawing open approach one with a reference and one without.  The one without has code that rebuilds the interface then opens the other.

Nikolay 2 -- When using the Register approach you register an interface that is associated with a drawing apparently performing the linkage between the drawing and stencil for you.  When using the CustomUI approach, the CustomUI is actually associated with the stencil and the drawing can't see it unless you define a reference.  So yes that's correct OnAction fails silently if there is no reference back to the stencil.

Andy -- I've finally gotten over the ribbon hump pretty much and am heading for code that works in 2003/2007/2010 using the CustomUI approach and, code identical but two different compiled versions for the Register approach being discussed in this thread.  I'm sure you already realize that your code will work with 2010, the UI is just ugly.  I've finally concluded that the ribbon provides some nice things but yes requires unplanned development not to mention reworking documentation.

Paul

AndyW

Paul, if only that were true, my code doesn't work as it stands with 2010 as I take pretty much full control of the existing UI within the Visio application. I have several commands bars that appear/disappear depending on what the user is doing, so this doesn't really get handled by all being bunged in an add-in tab. My application is not an add-in but runs within the Visio using automation. I have clients using 2003 and 2007 in mixed environments, so only a matter of time for 2010 to enter the mix.

The issues you have raised will certainly help though.

Andy
Live life with an open mind

paulv45

Wrapping this up a bit...
As it turns out the error reported in 2003 compile appears to be a bit bogus.
While you get it when compiling in VBA, it never appears to the user at run time.
So basically "live with it" is fine.
Hope this helps.
Paul

AndyW

I chose to pull my ribbon interface into a separate DLL with 2 interface classes, one to handle any ribbon stuff and one for the ribbon stuff to use as a callback to my main application. That way I have no conditional compiles to worry about and no ribbon code in my common code.
Live life with an open mind