CustomUI in ExternalLibrary

458 views
Skip to first unread message

Simon

unread,
Jun 24, 2011, 10:12:33 AM6/24/11
to Excel-DNA
Hi,

Sorry if this is a silly question.

I have some Ribbon XML declared in the .dna file and it works great.
When I move the code to another .dna file and reference that as an
ExternalLibrary from the root .dna file, the ribbon items no longer
appear.

I have checked that the ExternalLibrary reference is working OK as,
when I deliberately create bad XML in the referenced file, I get an
error from DNA.

Am I doing something obviously wrong?

Simon.

Govert van Drimmelen

unread,
Jun 25, 2011, 12:44:01 PM6/25/11
to Excel-DNA
Hi Simon,

Your ExcelRibbon-derived class might be in a .dna file as text, or in
a .dll referenced from a .dna file using ExternalReference. The .xml
used by default in the ExcelRibbon's GetCustomUI(..) is the .xml in
_that_ .dna file.

So if you chain the .dna files, with ExternalLibrary
Path="Myfile.dna", then it won't look up the tree to find the .xml, it
will just use the 'current' .dna file.

You can override GetCustomUI to load the xml string from anywhere you
like, say a resource in your assembly, or a separate file on disk.

-Govert

Simon

unread,
Jun 29, 2011, 5:35:45 AM6/29/11
to Excel-DNA
Hi Govert,

I have a couple of questions...

1. What is the difference between ExternalReference and
ExternalLibrary?

I have used <ExternalLibrary Path="MyDLL.dll"> to succesfully
reference a .dll with my ExcelRibbon-derived class. You mention I
should be using ExternalReference, which I can't get to work. Do you
have an example?

2. I am a little confused by your response regarding where the ribbon
XML should sit. From my experiments, I can only get the ribbon XML
working in a root .dna file regardless of any ExternalLibrary
settings. I have tried a number of combinations of ExternalLibrary
settings to both .dna and .dll files without success.

I'm not sure what you mean by '_that_ .dna file'. Are you saying that
the ribbon XML must exist in a .dna file that contains a reference to
the .dll file that has the ExcelRibbon-derived class? If this is the
case, then I have not been able to get this to work successfully.
This could, though, be down to my confusion over ExternalReference and
ExternalLibrary.

Simon.
> > Simon.- Hide quoted text -
>
> - Show quoted text -

Govert van Drimmelen

unread,
Jun 29, 2011, 1:59:16 PM6/29/11
to Excel-DNA
Hi Simon,

Sorry - my mistake above. There is no such thing as
'ExternalReference'.
In the reply it should have been <ExternalLibrary>. I discuss
<Reference> below, but that's not really relevant to the Ribbon
issues.

Excel-DNA exports types from:
1. Code as text in .dna files. These may be one or more <Project>
tags, each compiled at runtime to an assembly, or just code,
implicitly placed in its own <Project>.
2. Code referenced in pre-compiled assemblies (.dlls).

In a .dna file you can
1. Put some code directly, or in <Project> tags, and/or
2. Export a pre-compiled assembly using <ExternalLibrary>, and/or
3. Export (recursively) the stuff from another .dna file - this can
again be code, or further <ExternalLibrary>s.
(So a .dna file can have many <ExternalLibrary> tags (with .dlls or
further .dna files), and also have many <Project> tabs with code in.)

Each assembly is processed relative to a .dna file:
1. Pre-compiled .dll assemblies are processed relative to the .dna
file where the <ExternalLibrary> tag appeared.
2. Source code in .dna files are processed relative to the .dna file
where the source code is defined.

When an assembly has an ExcelRibbon-derived class, the class is loaded
into Excel as a COM add-in. The base implementation of GetCustomUI
which returns the xml string to Excel looks for an appropriate
<CustomUI>. tag in the .dna file _that the assembly is relative to_.
You can override the GetCustomUI call and do anything else you want.

This means you can have the following layout:
1. Suppose you have RootLibrary.xll and RootLibrary.dna containing
<DnaLibrary>
<ExternalLibrary Path="MyRibbonStuff.dna" />
<ExternalLibrary Path="SomeFunctions.dll" />
</DnaLibrary>

2. and you have MyRibbonStuff.dna with
<DnaLibrary>
<ExternalLibrary Path="RibbonHandlers.dll"/>
<CustomUI>
<customUI> .... Ribbon definition ....
</customUI
</CustomUI>
</DnaLibrary>

Then the ExcelRibbon-derived class in RibbonHandlers.dll will by
default use the customUI from MyRibbonStuff.dna.

You need to be quite careful with the <CustomUI> <customUI> nesting
there - I was a bit careless when setting this up.
The outer <CustomUI> is an Excel-DNA tag, and you can have one or more
of these under a <DnaLibrary>. Inside the <CustomUI> you have the
exact string that should be passed to Excel, this starts with
<customUI xmlns=.....>

One common implementation I've seen is to put the ribbon .xml into
your assembly as a resource, and override the ExcelRibbon.GetCustomUI
to return the string from the resource. That keeps the ribbon xml
string and the .dll with the handlers together. That works perfectly
with Excel-DNA too.
My starting point was testing all of it with the handler code defined
source in the .dna file. And since the .dna file is already .xml, it
made sense to have the ribbon stuff there too.

About <Reference> tags: These are used:
1. When there is code in a .dna file to compile, these are used as
Tools->References for the compiled projects.
2. When an assembly is loaded (from .dna file or from pre-
compiled .dll), the Assembly References must be resolved. <Reference>
tags allow this resolution to occur relative to the location of the
add-in, rather than only from the GAC or relative to the location of
the Excel.exe.
3. When packing, the <Reference> assemblies with Pack='true' are also
packed, and resolved at runtime when needed like 1. or 2. above.

(Libraries in <Reference> tags are not exported to Excel as add-ins
themselves. They are for use from the ExternalLibrary or .dna source
based assemblies which define add-ins.)

If you have more questions, or any of this does not agree with your
experience, please let me know.
Also, if you can think of how it could be better designed without
giving up flexibility, I'd welcome your thoughts.

Regards,
Govert

On Jun 29, 11:35 am, Simon <simon.mi...@solution7.co.uk> wrote:
> Hi Govert,
>
> I have a couple of questions...
>
> 1. What is the difference betweenExternalReferenceand
> ExternalLibrary?
>
> I have used <ExternalLibrary Path="MyDLL.dll"> to succesfully
> reference a .dll with my ExcelRibbon-derived class.  You mention I
> should be usingExternalReference, which I can't get to work. Do you
> have an example?
>
> 2. I am a little confused by your response regarding where the ribbon
> XML should sit.  From my experiments, I can only get the ribbon XML
> working in a root .dna file regardless of any ExternalLibrary
> settings.  I have tried a number of combinations of ExternalLibrary
> settings to both .dna and .dll files without success.
>
> I'm not sure what you mean by '_that_ .dna file'.  Are you saying that
> the ribbon XML must exist in a .dna file that contains a reference to
> the .dll file that has the ExcelRibbon-derived class?  If this is the
> case, then I have not been able to get this to work successfully.
> This could, though, be down to my confusion overExternalReferenceand
> ExternalLibrary.
>
> Simon.
>
> On Jun 25, 5:44 pm, Govert van Drimmelen <gov...@icon.co.za> wrote:
>
>
>
>
>
>
>
> > Hi Simon,
>
> > Your ExcelRibbon-derived class might be in a .dna file as text, or in
> > a .dll referenced from a .dna file usingExternalReference. The .xml

Simon

unread,
Jun 30, 2011, 6:36:36 AM6/30/11
to Excel-DNA
Hi Govert,

Thanks for the detailed response.

Firstly, I like the embedded resource approach. Stops people fiddling
and breaking the XML.

Looking at your comments and examples, I have not been able to
successfully wire ribbon XML to an externally referenced .dll in
anything other than the root .dna file.

E.G.'s

This works OK…

Root dna file:
<DnaLibrary RuntimeVersion="v4.0">
<ExternalLibrary Path="MyDll.dll" />
<CustomUI>
<customUI> .... Ribbon definition ....
</customUI>
</CustomUI>
</DnaLibrary>

Cannot get this working…

Root dna file:
<DnaLibrary RuntimeVersion="v4.0">
<ExternalLibrary Path="Ribbon.dna" />
</DnaLibrary>

Ribbon.dna file:
<DnaLibrary RuntimeVersion="v4.0">
<ExternalLibrary Path="MyDll.dll" />
<CustomUI>
<customUI> .... Ribbon definition ....
</customUI>
</CustomUI>
</DnaLibrary>

One thought about splitting the ribbon XML over multiple .dna files or
allowing multiple <CustomUI> tags in 1 .dna file - could you implement
the following?

<CustomUI ExternalLibrary=”MyDLL.dll” >
<customUI> .... Ribbon definition ....
</customUI>
</CustomUI>

It would allow you to split the <CustomUI> code across multiple files,
as they could be grouped by ExternalLibrary, or you could have many
<CustomUI> tags in one .dna file with the ExternalLibrary reference
qualifying which assembly to use.

I also agree with you about the confusion over <CustomUI> and
<customUI>. Maybe <DnaRibbon> would be better?

Thanks again for your help, amazing as always,

Simon.

Govert van Drimmelen

unread,
Jun 30, 2011, 9:21:09 AM6/30/11
to Excel-DNA
Hi Simon,

1. If you pack the .dna file into the .xll, then the ribbon .xml is
also hidden a bit. But the assembly resource plan is a good one.

2. Your second layout is perfect and definitely works for me - I
checked yesterday.
Are you using the latest version of Excel-DNA (I vaguely recall some
relevant changes)?
If so, something else is wrong on your side (like a type in the .xml).
But maybe it's just the version you're using.
(I can send my example or look at yours if you mail me.)

3. There is an option to have different ribbon pieces share a tab or
ribbon group. In the Distribution\Samples\Ribbon there are
SharedGroup1.dna & 2.dna which could be separate .xlls, or from a
single .dna/.xll as two ExternalLibraries.
I meant to provide the splitting flexibility you ask for by allowing
you to structure the .dna files. If it worked for you, I think you'd
have more than enough flexibility.
However, this still means you only have one .xml piece per ExcelRibbon-
derived class. Merging different .xml pieces for use by a single
ExcelRibbon class would be a bit tricky.
Anyway, by overriding GetCustomUI you can make the string anyway you
want, with no more Excel-DNA interference.

<DnaRibbon> is not great, since it is used for the <CommandBars> .xml
too. Maybe <DnaCustomUI> ?
Or maybe we just need better documentation. I'm looking forward to
your Ribbon blog posts ;-)

-Govert

Simon

unread,
Jun 30, 2011, 9:58:37 AM6/30/11
to Excel-DNA
Hi,

Now image the time we could have saved if I'd just used v.29 instead
of v.28 :-/

RTFRN!

Feeling guilty,

Simon.

BTW - <DnaCustomUI> sounds great.
Reply all
Reply to author
Forward
0 new messages