I'm using VSTO to design an application with an Excel interface. I want to hide the ribbon on startup (shouldn't be needed in the application) and re-display it on exit (if the user had it originally displayed), to avoid irritating people who use the application and want a ribbon the next time they open Excel.
I can hide the ribbon using essentially the following code in ThisWorkbook_Startup (from this question Excel 2007 Minimize the Ribbon programatically but Not the menu bar):
Office.CommandBars cbs = null;
cbs = Application.CommandBars;
foreach (Office.CommandBar commandBar in cbs)
{
if (commandBar.Name == "Ribbon")
{
this.Application.ActiveWindow.Activate();
Application.SendKeys("^{F1}", true);
}
}
However, the same code or similar variations from the previously referenced question do not seem to work when placed in either the ThisWorkbook_Shutdown or ThisWorkbook_BeforeClose methods. The code is hit but never seems to execute - the ribbon is never restored.
Is there another way to restore the ribbon on exit?
Thanks,
Andrew
Related
Hi I'm trying to add the current open contacts phone numbers to a ribbon.
I have created the ribbon and added a SplitButton which will contain the phone numbers.
In 'ThisAddin' when the current explorer changes it triggers an event which simply gets the item type. If its a contact it calls
//ThisAddin.cs on explorer change event - if is contact run:
Globals.Ribbons.CallContact.AddButton(contactItem.BusinessTelephoneNumber);
//Ribbon class
internal void AddButton(string name)
{
if (name != null && name.Count() > 2)
{
RibbonButton item = Globals.Factory.GetRibbonFactory().CreateRibbonButton();
item.Label = name;
item.ShowLabel = true;
this.newSplit.Items.Add(item);
}
}
This works once, first time opening a contact the phone number is displayed in the ribbon. Opening another contact window will cause the ribbon items to be added but are blank and null.
I'm simply trying to add the contacts phone numbers to the ribbon and leave them there while the user can open another contact and the same code runs adding the phone numbers to the ribbon.
I don't need to keep reference to the items once they are added. Thank you for the help. I feel there needs to be an invoke in here somewhere.
You must tell Outlook to refresh the ribbon. See https://learn.microsoft.com/en-us/visualstudio/vsto/walkthrough-updating-the-controls-on-a-ribbon-at-run-time?view=vs-2019 for the sample code.
You will need to specify a callback to retrieve the button's caption instead of hard-coding it in the ribbon's XML.
Note that since you can have multiple inspectors open, you must provide data specific to each item opened in its own inspector.
The Ribbon UI is a static thing because it is loaded once at startup (or before the window is shown). The best what you can do is to define callbacks and get them called wherever you need. For example, you can define 'getVisible' callback for your ribbon controls instead of adding new elements at runtime.
The IRibbonUI.Invalidate method invalidates the cached values for all of the controls of the Ribbon user interface.
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 getImage callback procedure for a button, the function is called once, the image loads, and then if the image needs to be updated, the cached image 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 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.
<customUI … OnLoad="MyAddinInitialize" …>
Dim MyRibbon As IRibbonUI
Sub MyAddInInitialize(Ribbon As IRibbonUI)
Set MyRibbon = Ribbon
End Sub
Sub myFunction()
MyRibbon.Invalidate() ' Invalidates the caches of all of this add-in's controls
End Sub
The Fluent UI is described in-depth 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)
Also, you may find the Walkthrough: Create a custom tab by using Ribbon XML helpful. Note, you can export an existing custom ribbon UI to the XML and continue dealing with a raw markup.
I've created an excel plugin using Add-In Express for .NET, but can't seem to figure out how to only show my ribbon when there is a certain set of data on the "Active" sheet.
If the worksheet doesn't contain a certain set of data in certain row of cells, I want to hide my ribbon since the buttons on the ribbon don't apply to all worksheets. When the user switches between different worksheets, I'd like to hide/show the ribbon as appropriate.
I tried using the AddinInitialize event, but this only fires once. I don't want to force the user to open the Excel file directly. They should be able to open Excel, then select the file from the File menu.
Here is what I have so far, but I don't know where to put it:
private void OnAddinInitialize(object sender, EventArgs e)
{
// note: this does not work all the time!
adxRibbonTab1.Visible = IsRibbonVisible();
}
private bool IsRibbonVisible()
{
var worksheet = ActiveSheet;
if (worksheet == null)
return false;
// only show ribbon when top row has certain column headings
var reader = new WorksheetReader(worksheet);
return reader.HasColumns(TopLeftCell, RequiredColumnNames);
}
I've tried creating an ADXExcelWorksheetEvents instance and overriding some of the events, but I'm not having much luck so far. I've not been able to find anything on their website for this type of workflow either.
I'd appreciate any help!
I found the answer. On the AddinModule designer, there is an "Events" item that I had to reference and then I was able to trap the following with my IsRibbonVisible() function:
WorksheetActivated
WorksheetDeactivated
WorkbookActivated
Problem solved!
I am developing a custom task pane for Microsoft PowerPoint 2010. I need the task pane to be synchronized between multiple application windows/presentations. The task panes are displayed using a toggle button on the ribbon.
Since PowerPoint 2010 displays each presentation in a different document window (which is different from 2007), I need to create a task pane separately for each window and synchronize them. I have followed the Microsoft tutorial on how to create task panes for multiple application windows, and I am using the CustomTaskPaneCollection.Add(UserControl, String, Object) method to specify which application window the task pane should be associated with. In this case the Object is the PowerPoint.DocumentWindow that the task pane should be associated with.
For some reason all of my task panes are created in the active window and not the window that I assign. For example, if I open 3 PowerPoint presentations and then toggle the task pane, all three task panes will be added to the active window.
This is the code I am using to add the task panes when the toggle is pressed:
public void AddAllTaskPanes()
{
PowerPoint.DocumentWindows windows = Globals.ThisAddIn.Application.Windows;
if(windows.Count > 0)
{
for (int i=1; i<=windows.Count; i++){
PowerPoint.DocumentWindow window = windows[i];
customTaskPane = this.CustomTaskPanes.Add(new UserControl1(), "My User Control", window);
customTaskPane.Visible = true;
}
}
}
It seems that this should successfully add each task pane to its specified window, and I cannot figure out why all of the task panes are being associate with the active window instead. I have done a lot of research into this issue and have not been able to find a solution. The closest I have found was this question, however the answer corresponds to PowerPoint 2007 and not 2010 like the question references.
Any insight into why PowerPoint may be behaving this way would be greatly appreciated.
I went the way of creating the TaskPanes from the PresentationAfterOpen and PresentationAfterNew Events which produces the same behaviour.
A note about the PresentationAfterOpen event, if the document selected by the user is already open, the event is still fired so you need to check if the CustomTaskPane has already been created for that document before creating a new one.
A way to overcome this problem is to create a pointer to the associated DocumentWindow in your CustomPane and enumerate through the CustomTaskPaneCollection checking for the associated one.
I created my own Excel Addin and after clicking the button displays a Custom Task Pane on right. Everything is fine but when I run this addin in Excel 2013. This displays Custom Task Panes with slide it open.For my Addin Flashes disappear and appear. It looks like a problem with the display.
Is there any solution? It looks very, very wrong.
PS. I'm sure they do not Set Custom Task Panes instance twice.
Display and hide performed using xxxxxxx.Visible = true / false;
Slide to close is Ok.
-------ThisAddIn.cs
_calcTaskPaneControl = new UI.CalcTaskPane();
_calcTaskPaneValue = this.CustomTaskPanes.Add(_calcTaskPaneControl, Common.CommonFunctions.GetLocalizeText("ThisAddIn_CalcTaskPaneTitle"));
_calcTaskPaneValue.VisibleChanged += new EventHandler(CalcTaskPaneValue_VisibleChanged);
--------MainRibbon.cs
Globals.ThisAddIn.CalcTaskPane.Visible = true;
I've noticed the same with Excel 2013. Whenever you set the visibility or the width, Excel 2013 reloads the taskpane. I had to updated all places to check if the CustomTaskPane not already is visible or invisible before setting it. So when your CTP is visible and you set Visible to True again, it will reload the taskpane. Excel 2010 doesn't do this.
I would like to add functionality to my Excel addin so I could load different Ribbons on demand.
At the moment I am trying by exporting the ribbon to XML and loading it
private Microsoft.Office.Core.IRibbonExtensibility ribbonObj;
protected override Microsoft.Office.Core.IRibbonExtensibility CreateRibbonExtensibilityObject()
{
DialogResult RibbonToLoad = MessageBox.Show("Yes = V2 No = V3", "Select Version", MessageBoxButtons.YesNo);
switch (RibbonToLoad)
{
case DialogResult.Yes:
ribbonObj = new RibbonV2();
return ribbonObj;
case DialogResult.No:
ribbonObj = new RibbonV3();
return ribbonObj;
}
return new RibbonV2();
}
The problema with this is I cannot find how to switch this Ribbon. I don't find it inside the Globals. object.
Also I tried without exporting to XML, but also I couldn't achieve the load on demand of a different ribbon while running(e.g. clicking a button on a WPF window...)
Any idea how to get this? I would like to have the possibility of loading different ribbons on the same addin(but only one would be present at once)
You can't manage the process of loading ribbon controls. But you can change visibility of your controls at runtime. The IRibbonUI interface provides the Invalidate and InvalidateControl methods that allow to trigger your callbacks where you can change visibility at runtime (getVisible).
In the following example, starting the host application triggers the onLoad event procedure that then calls a procedure which creates an object representing the Ribbon UI. Next, a callback procedure is defined that invalidates all of the controls on the UI and then refreshes the UI.
The following is the XML markup for Office to load the custom ribbon:
<customUI … onLoad=”MyAddInInitialize” …>
The following is the callback method for the onLoad event:
Dim MyRibbon As IRibbonUI
Sub MyAddInInitialize(Ribbon As IRibbonUI)
Set MyRibbon = Ribbon
End Sub
Sub myFunction()
‘ Invalidates the caches of all of this add-in’s controls
MyRibbon.Invalidate()
End Sub
You can read more about the 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)