MS Project COM: Click on a Ribbon UI button using COM - vsto

I have 2 different .NET projects:
1) MS Project 2010 VSTO project: This project adds a custom ribbon (using XML) to MS Project's ribbon UI. There is a button on this custom ribbon (called "Push_changes"). This project has been packaged into a "VSTO package" and installed on my local machine.
2) I have another .NET console application that has a reference to MS Project Object Library (COM object). Using COM, I am able to start a new instance of MS Project 2010. As a next step, I want to be able to get to the Ribbon (specifically the one that I added in Step 1, using the VSTO project). I then want to get to the "Push_changes" button and click on it (through code).
Now I tried, going through the CommandBars collection, but it doesn't seem to contain anything related to "Ribbon". Enumerating through the CommandBars collection, I can see that there is a CommandBar called "Ribbon", but it says that it has "0" controls on it.
Any help would be appreciated

Assembly which implements Add-on with a ribbon contains a COM Visible class inherited from Microsoft.Office.Core.IRibbonExtensibility.
One of public methods from that class implements that onClick action.
You can access collection of COM Add-Ons through Application.COMAddIns and access that Add-In by name.

Related

Word VSTO - Document Changed Event

we are using the Application.DocumentChange event so that when a document is loaded, it can check the name of the document, and then if it is named in a certain way show or hide buttons on the ribbon.
If I use the code below it works really well, it shows or hides the buttons correctly.
But when I run the addin in debug mode from Visual Studio, when the document is closing it gives this message.
System.Runtime.InteropServices.COMException: 'This command is not available because no document is open.'
As you can see I tried to put in an if statement to stop it running the code but it didnt work.
If I just install my addin, Word does not seem to crash or have any problems, maybe I shouldnt worry about it?
Thanks
Private Sub Application_DocumentChange() Handles Application.DocumentChange
If Globals.ThisAddIn.Application.Documents.Count > 0 Then
If Globals.ThisAddIn.Application.ActiveDocument.BuiltInDocumentProperties("Title").Value = "Document Name Here" Then
Globals.Ribbons.VisualfilesTab.AttachEvidence.Visible = True
Else
Globals.Ribbons.VisualfilesTab.GetAuthorisation.Visible = True
End If
End If
End Sub
Consider switching your custom UI to the ribbon XML over the designer-generated custom ribbon UI. You can export your existing custom UI to the ribbon XML markup. See How to: Export a ribbon from the Ribbon Designer to Ribbon XML for more information.
You can customize the Ribbon UI by using callback procedures in COM add-ins. For each of the callbacks that the add-in implements, the responses are cached.
For example, if an add-in writer implements the getVisible callback procedure for a button, the function is called once, the state is loaded, and then if the visibility state needs to be updated, the cached state is used instead of recalling the procedure. This process remains in place until the add-in signals that the cached values are invalid by using the Invalidate or IRibbonUI.InvalidateControl method, at which time, the callback procedure is again called and the return response is cached. The add-in can then force an immediate update of the UI by calling the Refresh method.
Read more about the the Fluent UI (aka Ribbon UI) in the following articles:
Customizing the 2007 Office Fluent Ribbon for Developers (Part 1 of 3)
Customizing the 2007 Office Fluent Ribbon for Developers (Part 2 of 3)
Customizing the 2007 Office Fluent Ribbon for Developers (Part 3 of 3)

How do you add a 'public partial class ThisWorkbook' to a VSTO application in C#?

I am trying to add an ActionPane to an Excel VSTO Add-in. I need to access the ThisWorkbook.ActionsPane collection to add my action panes.
The Microsoft documentation at:
https://learn.microsoft.com/en-us/visualstudio/vsto/how-to-add-an-actions-pane-to-word-documents-or-excel-workbooks?view=vs-2019
says:
To show the actions pane, add the user control to the Controls
property of the ThisDocument.ActionsPane field (Word) or
ThisWorkbook.ActionsPane field (Excel).
Add the following code to the ThisDocument or ThisWorkbook class as a
class-level declaration (do not add this code to a method).
This implies that I need to add a ThisWorkbook class to the VSTO solution. My questions are:
What base class contains the ActionsPlane collection?
How would I add a class derived from this base class to my VSTO?
Some on-line examples of a ThisWorkbook class contain regions that are designer generated.
My workload includes every VSTO item available. There are no Excel items at all under 'Add New Item' or 'Add New User Control' in Visual Studio 2019. Beyond the Ribbon Bar, there are no designers for VSTO.
The only way that I see to do this is to add a ThisWorkbook class manually.
Am I correct in saying that any designers that may have existed in previous versions of Visual Studio, no longer exist in Visual Studio 2019?
You need to differentiate document-level and application-level add-ins.
An actions pane is a customizable Document Actions task pane that is attached to a specific Microsoft Office Word document or Microsoft Office Excel workbook. The actions pane is hosted inside the Office task pane along with other built-in task panes, such as the XML Source task pane in Excel or the Styles and Formatting task pane in Word. You can use Windows Forms controls or WPF controls to design the actions pane user interface.
Read more about Actions panes in the How to: Add an Actions Pane to Word Documents or Excel Workbooks article if you are developing a document-level add-in.
If you are developing an application-level add-in you may be interested in using Custom task panes. Task panes are user interface panels that are typically docked to one side of a window in a Microsoft Office application. Custom task panes give you a way to create your own task pane and provide users with a familiar interface to access your solution's features. For example, the interface can contain controls that run code to modify documents or display data from a data source. See Walkthrough: Automate an application from a custom task pane to get started quickly.

VSTO Addin disable builtin outlook button on Appointment (Recurring)

I am developing an Outlook Addin (VSTO, C#). I created the Addin with the following steps in VS: New->Project , then
From all what I learned in the meantime I fear that this DOES NOT create a COM-AddIn. But all tutorials listed below refer to COM AddIns.
I am looking for a step by step tutorial of how I can disable the builtin OUtlook Button which converts an appointment into a recurring appointment.
I already read a lot about fluent ribbons, like here
Programmaticaly disable existing button in outlook compose window ribbon
https://learn.microsoft.com/de-de/office/vba/library-reference/concepts/overview-of-the-office-fluent-ribbon
But I am just no able to put this into action for my purpose:
1.) I implemented in my Addin Class
public partial class ThisAddIn : Office.IRibbonExtensibility
...
string Office.IRibbonExtensibility.GetCustomUI(string RibbonID)
{
throw new NotImplementedException();
}
I set the breakpoint on the Exception. But running the addin (in Debugger) never stopped at that point.
I tried what is mentioned here:
IRibbonExtensibility GetCustomUI not called
I added [ComVisible(true)] to the VSTO AddIn Class. Does not work either. I also made sure that the Addin is still loaded.
2.) I am not sure how I could that with Outlook. It says that Outlook has several xml files (one per inspector?)
3.) I am not sure whether I would be able to dynamically change the buttons. Athough the second tutorial talks about that, but i am not sure if callbacks are the right concept here, because my application activley wants to decide when a button should be active/inactive, so there is no waiting for a callback to happen?
I know that the links provided above contain step-by-step tutorials. But there are just too many open questions to these tutorials.
You have already found a complete guide on how to repurpose a ribbon button. Just use command tag with the getEnabled attribute defined in your ribbon XML markup. For example:
<?xml version="1.0" encoding="UTF-8"?>
<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui" onLoad="Ribbon_Load">
<commands>
<command idMso="Permissions" getEnabled="OnGetEnabled" />
</commands>
</customUI>
You can repurpose built-in ribbon controls, see Temporarily Repurpose Commands on the Office Fluent Ribbon for more information.
VSTO provides two ways of customizing the Fluent UI:
Walkthrough: Create a custom tab by using the Ribbon Designer
Walkthrough: Create a custom tab by using Ribbon XML
Unfortunately, the UI designer doesn't support all the features of the Fluent UI. So, you need to stick with a raw XML markup described in one of the articles mentioned above.

How to add a group to a (VBA) custom ribbon without xmlns/idQ?

Situation:
Users have an existing custom ribbon that is added via a .PPAM (combination of VBA macros and Ribbon customization XML).
We want to add a group to that custom ribbon via our managed COM add-in
For custom ribbons from other managed COM add-ins this is feasible via the xmlns:foo="bar" & idQ that can be extracted from the customUI Link
Complication:
Custom Ribbons from non-managed add-ins seem to have no xmlns namespace, they do not show up in the customUI
Even via PowerPoint/Office the user can not customize those ribbons.
Any idea how we could achieve adding buttons?
We can request changes to the non-managed/VBA add-in.
VBA add-ins don't have their own namespace by default, but can have one. If you create a custom namespace, then multiple VBA add-ins can share the same tab on the ribbon, for example.
<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui"
xmlns:nsMySpace="SomeName">
Then to create a new tab that other add-ins can share:
<tab idQ="nsMySpace:MySpace_Tab" label="MyTabLabel">
In addition to Steve's answer we've discovered that VBA add-ins have a default namespace even when none is specified in their customUI.
You can extract the namespace by adding a control from the ribbon to the Quick Access and then exporting the UI Customizations. The resulting file should show:
<mso:cmd app="PowerPoint" dt="1" />
<mso:customUI xmlns:x1="C:\Users\USERNAME\AppData\Roaming\Microsoft\AddIns\Addin.ppam">
So the default namespace seems to be the complete Path to the add-in.
From a high perspective two add-ins can share a ribbon tab for controls because they are loaded into a single PowerPoint instance. When you develop a macro enabled file with a custom UI - only this file can be opened at the same time. But two add-ins can be run for the file/template. That's why idQ is intended to use by add-ins.
You can read more about the Fluent UI (Ribbon UI) in the following series of articles in MSDN:
Customizing the 2007 Office Fluent Ribbon for Developers (Part 1 of 3)
Customizing the 2007 Office Fluent Ribbon for Developers (Part 2 of 3)
Customizing the 2007 Office Fluent Ribbon for Developers (Part 3 of 3)

MS Project VSTO: Closing MS Project causes it to hang indefinetely

I have replicated this issue in both Project 2010 and 2013.
I developed a VSTO addin, using Visual Studio 2010. In this addin, I have exposed a COMVisible method.
I also have a different (non .NET) application, which then instantiates the Project COM object, searches for my addin and calls the method that I marked as COMVisible.
This causes Project to open a "new" Project file and write something to it.
This non-.NET application, after calling the COM method in my addin, stops execution (without closing MS Project).
I then close the newly created Project (not MS Project, just the file). Everything is fine; however, when I try to close MS Project, it hangs indefinitely. In the Task Manager, it is still shown as "Running" and clicking on the MS Project window brings up a "Switch To", "Retry", "Cancel" dialog, informing me that some other application is busy...
Surprisingly, if I choose to NOT close the newly created Project file, and simply close the MS Project window, it closes normally.
What might be going on here?
Ok, after much investigation, I found the answer to the problem. Basically the COM class exposed from my VSTO Addin needs to inherit "StandardOleMarshalObject".
The reason for this is because the COM method in my Addin was accessing the Project Object Model on a secondary thread (the thread of the calling application). This is a big no no. Deriving from that class marshals all call on that secondary thread to the primary UI thread, thus fixing the problem.