| 
                
         | 
  
  
        | 
				                                 Eriq VanBibber                				 
                					 
                     
                
                
                
                 Guest                 
                 
                
                
                                 
                                                                
         | 
        
                
                
                I'm trying to create a modular set of addins.  Each feature will be hosted by a separate .net assembly.
 
 I'd like to have a button from ProjectA get added to the same ribbon group as ProjectB.
 
 Is this possible?  i have tried simply setting the ribbon group ID to the same value, but then nothing shows.                 |   
                 
         | 
  
  
        
                
                
                  
						| 
				                Posted 02 Oct, 2019 19:36:18
						 | 
                        
                                
                                
                                                                                                
                         | 
                        
                                                                Top
                         | 
                   
                 
                 
         | 
  
    
        | 
				                                 Andrei Smolin                				 
                					 					 
                
                
                
                 Add-in Express team                 
                 
                
                
                                 
                                        Posts: 19178 
                                                        Joined: 2006-05-11 
                                                
         | 
        
                
         | 
  
  
        
                
                
                  
						| 
				                Posted 03 Oct, 2019 02:12:12
						 | 
                        
                                
                                
                                                                                                
                         | 
                        
                                                                Top
                         | 
                   
                 
                 
         | 
  
    
        | 
				                                 Eriq VanBibber                				 
                					 
                     
                
                
                
                 Guest                 
                 
                
                
                                 
                                                                
         | 
        
                
                
                andrei,
 
 thanks for that pointer.
 
 however, it doesn't seem to apply to my case.
 
 i will have a "master" addin for which several "sub-addins" can be installed/added after the main addin has been installed.  the "plugin for the plugin" type of thing.
 
 So, i have this separate assembly that is simply an ADXAddinAdditionalModule.  Then, i add this to the "Modules" property of the main addin.  (though, i don't yet know how to do this at runtime).
 
 So, how would i have a button in my "additional module" merge into an existing ribbon group from the main addin?
 
 Does my question make sense?
 
 Regards,
 Eriq                 |   
                 
         | 
  
  
        
                
                
                  
						| 
				                Posted 04 Oct, 2019 18:46:37
						 | 
                        
                                
                                
                                                                                                
                         | 
                        
                                                                Top
                         | 
                   
                 
                 
         | 
  
    
        | 
				                                 Andrei Smolin                				 
                					 					 
                
                
                
                 Add-in Express team                 
                 
                
                
                                 
                                        Posts: 19178 
                                                        Joined: 2006-05-11 
                                                
         | 
        
                
                
                Hello Eriq,
 
 You are right: I was pointing to a wrong direction. I've tested this and found that having an ADXRibbonTab on the add-in module or on an additional module generates a separate XML tab element whatever the settings are. This is by design, unfortunately. A way to solve this would be to intercept the BeforeRibbonCreate event of the add-in module and do the following:
 - Identify the target Ribbon container (tab or group) that will have a combined set of controls.
 - Identify the source Ribbon container providing Ribbon controls on the additional module.
 - Move the Ribbon components from the source container to the target container.
 - Delete the source container.
 
 The last step is required because right after raising the BeforeRibbonCreate event, Add-in Express copies Ribbon tabs from the additional module to the main one.
 
 
 Andrei Smolin
 Add-in Express Team Leader                 |   
                 
         | 
  
  
        
                
                
                  
						| 
				                Posted 07 Oct, 2019 05:53:05
						 | 
                        
                                
                                
                                                                                                
                         | 
                        
                                                                Top
                         | 
                   
                 
                 
         | 
  
    
        | 
				                                 Eriq VanBibber                				 
                					 
                     
                
                
                
                 Guest                 
                 
                
                
                                 
                                                                
         | 
        
                
                
                Ok.  I had already thought about that before creating this thread.  however, i didn't know about that last part - 'delete the source container'.
 
 yet...how to do this?  I see in the designer file that the ribbon tab control is added to the 'components' variable.
 Remove it from there?
 
 i have tried disposing of the tab, setting it to null, and removing it from the components collection, but all cases give me an exception with something about GetAttributes.
 
 -Eriq                 |   
                 
         | 
  
  
        
                
                
                  
						| 
				                Posted 07 Oct, 2019 12:05:59
						 | 
                        
                                
                                
                                                                                                
                         | 
                        
                                                                Top
                         | 
                   
                 
                 
         | 
  
    
        | 
				                                 Andrei Smolin                				 
                					 					 
                
                
                
                 Add-in Express team                 
                 
                
                
                                 
                                        Posts: 19178 
                                                        Joined: 2006-05-11 
                                                
         | 
        
                
                
                Hello Eriq, 
 
 foreach (var item in this.components.Components)
{
    System.Diagnostics.Debug.WriteLine("!!! " + item.ToString());
} 
 
 In a sample add-in, this prints the following:
 
 [29872] !!!  [AddinExpress.MSO.ADXRibbonTab] 
[29872] !!!  [AddinExpress.MSO.ADXRibbonGroup] 
[29872] !!!  [AddinExpress.MSO.ADXRibbonButton] 
 
 
 The following code fragment is from https://www.add-in-express.com/creating-addins-blog/2012/01/20/load-office-addin-on-condition/: 
 
 private void RemoveComponents()
{
    for (int i = this.components.Components.Count - 1; i >= 0; i--)
        this.components.Remove(this.components.Components[i]);
} 
 
 Eriq VanBibber writes:
 all cases give me an exception with something about GetAttributes 
 
 Please provide details. 
 
 
 Andrei Smolin
 Add-in Express Team Leader                 |   
                 
         | 
  
  
        
                
                
                  
						| 
				                Posted 08 Oct, 2019 01:14:17
						 | 
                        
                                
                                
                                                                                                
                         | 
                        
                                                                Top
                         | 
                   
                 
                 
         | 
  
    
        | 
				                                 Eriq VanBibber                				 
                					 
                     
                
                
                
                 Guest                 
                 
                
                
                                 
                                                                
         | 
        
                
                
                Ok.  Clearly i'm missing something.  I followed similar logic as what you provided.
 
 Here's my code:
 
 
    Private Sub AddinModule_OnRibbonBeforeCreate(sender As Object, ribbonId As String) Handles Me.OnRibbonBeforeCreate
        For Each modu In Me.Modules.OfType(Of ADXAddinAdditionalModuleItem)
            If modu.Module IsNot Nothing AndAlso modu.ModuleProgID = "PTFO_MessageHeaderViewer.PTO_MessageHeaderViewer" Then
                Dim ribbon As ADXRibbonTab
                ribbon = modu.Module.GetContainer.Components.OfType(Of IComponent).FirstOrDefault(Function(__) TypeOf __ Is ADXRibbonTab)
                While ribbon IsNot Nothing
                    modu.Module.GetContainer.Remove(ribbon)
                    While ribbon.Controls.Count
                        Dim grp = ribbon.Controls(0)
                        grp.AsRibbon.ADXModule = Me
                        ribbon.Controls.RemoveAt(0)
                        tabPTO.Controls.Add(grp)
                    End While
                    modu.Module.GetContainer.Remove(ribbon)
                    ribbon = modu.Module.GetContainer.Components.OfType(Of IComponent).FirstOrDefault(Function(__) TypeOf __ Is IADXRibbonComponent)
                End While
                Dim rc As IADXRibbonComponent
                rc = modu.Module.GetContainer.Components.OfType(Of IADXRibbonComponent).FirstOrDefault
                While rc IsNot Nothing
                    modu.Module.GetContainer.Remove(rc)
                End While
                For Each grp In GetContainer.Components.OfType(Of ADXRibbonTab)
                    grp.AsRibbon.ADXModule = Me
                Next
            End If
        Next
    End Sub
 
 
 
 What i find is that after this method completes, i get a startup exception.
 From what i can gather, the 'ProcessChildren' method is calling a 'GetAttributes' method that is failing with a null-ref exception.
 
 using reflection, i find that the ADXRibbonGroup.GetAttributes method could fail here:
 
        protected override SortedList GetAttributes()
        {
            SortedList sortedLists = new SortedList();
            IADXRibbonComponent asRibbon = base.AsRibbon;
            if (!this.shared)
            {
                sortedLists["getVisible"] = "getVisible_Callback";
                if (this.IdMso == string.Empty)
                {
                    if (asRibbon.ADXModule.Namespace == string.Empty) // <==  This throws the error because ADXModule is null!
                    {
                        sortedLists["id"] = asRibbon.Id;
                    }
                    else
                    {
                        sortedLists["idQ"] = string.Concat("default:", asRibbon.Id);
                    }
         ...
         // other code follows here.
 
 
 
 Here's the full error text reported:
 
Detailed technical information follows: 
---
Date and Time:         10/8/2019 10:53:36 AM
Machine Name:          XXXXXXXXX
IP Address:            XX.XX.XX.XX
Current User:          XXXXXXXXXxx
Application Domain:    C:ProjectsTFSOverlookOutlookToolsForPowerUsersinDebug
Assembly Codebase:     file:///C:/Windows/assembly/GAC_MSIL/AddinExpress.MSO.2005/9.4.4644.0__4416dd98f0861965/AddinExpress.MSO.2005.dll
Assembly Full Name:    AddinExpress.MSO.2005, Version=9.4.4644.0, Culture=neutral, PublicKeyToken=4416dd98f0861965
Assembly Version:      9.4.4644.0
Exception Source:      AddinExpress.MSO.2005
Exception Type:        System.NullReferenceException
Exception Message:     Object reference not set to an instance of an object.
Exception Target Site: GetAttributes
---- Stack Trace ----
   AddinExpress.MSO.ADXRibbonGroup.GetAttributes()
       AddinExpress.MSO.2005.dll: N 0474 (0x1DA) IL 
   AddinExpress.MSO.ADXRibbonCustomControl.AddinExpress.MSO.IADXRibbonComponent.get_Attributes()
       AddinExpress.MSO.2005.dll: N 0000 (0x0) IL 
   AddinExpress.MSO.ADXAddinModule.ProcessChildren(xmlData As XmlTextWriter, ribbonElement As IADXRibbonComponent, ribbonID As String, uniqueId As Int32, ribbonControl As IRibbonControl)
       AddinExpress.MSO.2005.dll: N 0088 (0x58) IL 
   AddinExpress.MSO.ADXAddinModule.ProcessChildren(xmlData As XmlTextWriter, ribbonElement As IADXRibbonComponent, ribbonID As String, uniqueId As Int32, ribbonControl As IRibbonControl)
       AddinExpress.MSO.2005.dll: N 0359 (0x167) IL 
   AddinExpress.MSO.ADXAddinModule.AddinExpress.MSO.IRibbonExtensibility.GetCustomUI(RibbonID As String)
       AddinExpress.MSO.2005.dll: N 1704 (0x6A8) IL 
                  |   
                 
         | 
  
  
        
                
                
                  
						| 
				                Posted 08 Oct, 2019 12:53:25
						 | 
                        
                                
                                
                                                                                                
                         | 
                        
                                                                Top
                         | 
                   
                 
                 
         | 
  
    
        | 
				                                 Andrei Smolin                				 
                					 					 
                
                
                
                 Add-in Express team                 
                 
                
                
                                 
                                        Posts: 19178 
                                                        Joined: 2006-05-11 
                                                
         | 
        
                
                
                Hello Eriq, 
 
     Private Sub AddinModule_OnRibbonBeforeCreate(sender As Object, ribbonId As String) Handles MyBase.OnRibbonBeforeCreate
        For Each aModuleItem As AddinExpress.MSO.ADXAddinAdditionalModuleItem In Me.Modules
            If aModuleItem.Module IsNot Nothing AndAlso aModuleItem.ModuleProgID = "ClassLibrary1.AddinAdditionalModule1" Then
                Dim componentsToMove As List(Of IComponent) = New List(Of IComponent)()
                Dim sourceContainer As IContainer = aModuleItem.Module.GetContainer
                Dim targetContainer As IContainer = Me.GetContainer
                Dim sourceTab As ADXRibbonTab = Nothing
                Dim targetTab = Me.AdxRibbonTab1
                For Each aComponent As IComponent In sourceContainer.Components
                    If TypeOf aComponent Is ADXRibbonTab Then
                        sourceTab = CType(aComponent, ADXRibbonTab)
                        Exit For
                    End If
                Next
                For Each aComponent As IComponent In sourceContainer.Components
                    If TypeOf aComponent Is IADXRibbonComponent Then
                        Dim cmp As IADXRibbonComponent = CType(aComponent, IADXRibbonComponent)
                        If cmp IsNot sourceTab Then
                            componentsToMove.Add(aComponent)
                        End If
                    End If
                Next
                For Each item As IComponent In componentsToMove
                    If TypeOf item Is IADXRibbonComponent Then
                        Dim cmp As IADXRibbonComponent = CType(item, IADXRibbonComponent)
                        If cmp.Root Is sourceTab Then
                            cmp.ADXModule = Me
                        End If
                        If TypeOf cmp Is ADXRibbonGroup Then
                            sourceTab.Controls.Remove(CType(cmp, ADXRibbonGroup))
                            targetTab.Controls.Add(CType(cmp, ADXRibbonGroup))
                        End If
                    End If
                    sourceContainer.Remove(item)
                    targetContainer.Add(item)
                Next
                sourceContainer.Remove(sourceTab)
            End If
        Next
    End Sub 
 
 
 Andrei Smolin
 Add-in Express Team Leader                 |   
                 
         | 
  
  
        
                
                
                  
						| 
				                Posted 09 Oct, 2019 08:46:41
						 | 
                        
                                
                                
                                                                                                
                         | 
                        
                                                                Top
                         | 
                   
                 
                 
         | 
  
    
        | 
				                                 Eriq VanBibber                				 
                					 
                     
                
                
                
                 Guest                 
                 
                
                
                                 
                                                                
         | 
        
                
                
                Thanks!!!
 
 It seems the component.Root thing was something i missed and didn't know about.
 
 Regards,
 Eriq                 |   
                 
         | 
  
  
        
                
                
                  
						| 
				                Posted 09 Oct, 2019 10:47:54
						 | 
                        
                                
                                
                                                                                                
                         | 
                        
                                                                Top
                         | 
                   
                 
                 
         | 
  
    
        | 
				                                 Andrei Smolin                				 
                					 					 
                
                
                
                 Add-in Express team                 
                 
                
                
                                 
                                        Posts: 19178 
                                                        Joined: 2006-05-11 
                                                
         | 
        
                
                
                Welcome!
 
 
 Andrei Smolin
 Add-in Express Team Leader                 |   
                 
         | 
  
  
        
                
                
                  
						| 
				                Posted 10 Oct, 2019 02:37:00
						 | 
                        
                                
                                
                                                                                                
                         | 
                        
                                                                Top
                         | 
                   
                 
                 
         |