Excel VSTO自定义任务窗格的可用性 [英] Excel VSTO Custom task Pane availability
问题描述
我写了一个Excel应用程序级VSTO.但是有些我不明白.我创建的自定义功能区选项卡可在应用程序级别使用,这适用于所有打开的工作簿.
I writting an Excel application-level VSTO. But there is something I do not understand. The custom ribbon tab I created is available at the application level, meaning for all opened workbooks.
我使用 Ribbon Designer 创建了功能区选项卡,并通过ThisAddIn.cs
文件中的函数setRibbonControlState
调用了它的一个实例.该函数由我从ThisAddIn_startup
处理的3个事件调用:
I created the ribbon tab using the Ribbon Designer and I call an instance of it through a function setRibbonControlState
in the ThisAddIn.cs
file. The function is called by the 3 events I handle from the ThisAddIn_startup
:
((Excel.AppEvents_Event)Application).NewWorkbook += new Excel.AppEvents_NewWorkbookEventHandler(App_NewWorkbook);
Application.WorkbookBeforeClose += new Excel.AppEvents_WorkbookBeforeCloseEventHandler(App_WorkbookBeforeClose);
Application.WorkbookOpen += new Excel.AppEvents_WorkbookOpenEventHandler(App_NewWorkbook);
在此级别上,一切正常.
At this level, everything works fine.
然后,我创建了3个用户"选项卡控件(当然每个课程都有一个.cs
文件)以显示在3个CustomTaskPanes中.我在功能区选项卡的load
事件处理程序中创建了3个CustomTaskPanes,并编写了一些函数来显示相应的任务窗格和内部控件的相应选项卡.这是ribbon.cs的部分代码,显示了我如何创建和显示CustomTaskPane:
Then I created 3 User Tab Controls (with a .cs
file for each of course) to display in 3 CustomTaskPanes. I created the 3 CustomTaskPanes in the load
event handler of the ribbon tab and wrote functions to display the appropriate Task Pane and the appropriate Tab of the inner control. Here is a partial code of the ribbon.cs, showing how I created and display the CustomTaskPane:
private CustomTaskPane tsPane;
private void tsFinStRibbon_Load(object sender, RibbonUIEventArgs e)
{
// Custom task pane
tsPane = Globals.ThisAddIn.CustomTaskPanes.Add(new tsDataControl(), "Data", Globals.ThisAddIn.Application.ActiveWindow);
tsPane = Globals.ThisAddIn.CustomTaskPanes.Add(new tsStControl(), "Statements", Globals.ThisAddIn.Application.ActiveWindow);
tsPane = Globals.ThisAddIn.CustomTaskPanes.Add(new tsPubControl(), "Publishing", Globals.ThisAddIn.Application.ActiveWindow);
tsPane.DockPosition = Microsoft.Office.Core.MsoCTPDockPosition.msoCTPDockPositionRight;
tsPane.Visible = false;
}
// Données
private tsDataControl setDataPane()
{
tsPane = Globals.ThisAddIn.CustomTaskPanes[0];
tsDataControl control = tsPane.Control as tsDataControl;
if (!tsPane.Visible)
{
tsPane.Width = 320;
tsPane.Visible = true;
}
return control;
}
// Etats
private tsStControl setStPane()
{
tsPane = Globals.ThisAddIn.CustomTaskPanes[1];
tsStControl control = tsPane.Control as tsStControl;
if (!tsPane.Visible)
{
tsPane.Width = 320;
tsPane.Visible = true;
}
return control;
}
// Publications
private tsPubControl setPubPane()
{
tsPane = Globals.ThisAddIn.CustomTaskPanes[2];
tsPubControl control = tsPane.Control as tsPubControl;
if (!tsPane.Visible)
{
tsPane.Width = 320;
tsPane.Visible = true;
}
return control;
}
// Balance générale
private void tsBtn1A_Click(object sender, RibbonControlEventArgs e)
{
if(Globals.ThisAddIn.CustomTaskPanes.Count != 0)
{
tsDataControl control = setDataPane();
control.selectTab(0);
}
}
// balance tiers
private void tsBtn1B_Click(object sender, RibbonControlEventArgs e)
{
if (Globals.ThisAddIn.CustomTaskPanes.Count != 0)
{
tsDataControl control = setDataPane();
control.selectTab(1);
}
}
// Calcul des états
private void tsBtn2A_Click(object sender, RibbonControlEventArgs e)
{
if (Globals.ThisAddIn.CustomTaskPanes.Count != 0)
{
tsStControl control = setStPane();
RibbonSplitButton btn = (RibbonSplitButton)sender as RibbonSplitButton;
string btnId = btn.Name;
control.selectTab(0, btnId);
}
}
// -- Calcul des états avec notes annexes
private void tsBtn2A1_Click(object sender, RibbonControlEventArgs e)
{
if(Globals.ThisAddIn.CustomTaskPanes.Count != 0)
{
tsStControl control = setStPane();
RibbonButton btn = (RibbonButton)sender as RibbonButton;
string btnId = btn.Name;
control.selectTab(0, btnId);
}
}
// -- Calcul des états sans notes annexes
private void tsBtn2A2_Click(object sender, RibbonControlEventArgs e)
{
if (Globals.ThisAddIn.CustomTaskPanes.Count != 0)
{
tsStControl control = setStPane();
RibbonButton btn = (RibbonButton)sender as RibbonButton;
string btnId = btn.Name;
control.selectTab(0, btnId);
}
}
// Bilan
private void tsBtn2B_Click(object sender, RibbonControlEventArgs e)
{
if (Globals.ThisAddIn.CustomTaskPanes.Count != 0)
{
tsStControl control = setStPane();
RibbonButton btn = (RibbonButton)sender as RibbonButton;
string btnId = btn.Name;
control.selectTab(1, btnId);
}
}
// -- Bilan actif
private void tsBtn3A_Click(object sender, RibbonControlEventArgs e)
{
if (Globals.ThisAddIn.CustomTaskPanes.Count != 0)
{
tsStControl control = setStPane();
RibbonSplitButton btn = (RibbonSplitButton)sender as RibbonSplitButton;
string btnId = btn.Name;
control.selectTab(1, btnId);
}
}
// -- Bilan Passif
private void tsBtn3B_Click(object sender, RibbonControlEventArgs e)
{
if (Globals.ThisAddIn.CustomTaskPanes.Count != 0)
{
tsStControl control = setStPane();
RibbonSplitButton btn = (RibbonSplitButton)sender as RibbonSplitButton;
string btnId = btn.Name;
control.selectTab(1, btnId);
}
}
当我打开Excel时,只能从初始电子表格访问内部控件中的相应任务窗格和选项卡.我打开或创建的任何其他电子表格都提供功能区选项卡,但是当我单击其任何按钮时,自定义任务窗格不会显示.
When I open Excel, I can access the appropriate task pane and tab in the inner control only from the initial spreadsheet. Any further spreadsheet I open or create provides the ribbon tab but when I click on any of its button, the custom task panes do not show up.
我试图从ThisAddIn.cs
文件创建任务窗格,并且有效地创建了它们,但是只有当我单击初始电子表格中的功能区时,它们才会做出反应.
I tried to created the tasks panes from the ThisAddIn.cs
file, and it effectively creates them, but they react only when I click on the ribbon from the initial spreadsheet.
在我的阅读中,我找不到有效地将功能区附加到任务窗格以使其正常运行的方法.
In my reading, I could not find a way to efficiently attach the ribbon to the tasks panes to make it behave correctly.
有人知道如何解决吗?
谢谢.
编辑
这是完整的ThisAddIn.cs
代码:
public partial class ThisAddIn
{
private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
// Events handlers
((Excel.AppEvents_Event)Application).NewWorkbook += new Excel.AppEvents_NewWorkbookEventHandler(App_NewWorkbook);
Application.WorkbookBeforeClose += new Excel.AppEvents_WorkbookBeforeCloseEventHandler(App_WorkbookBeforeClose);
Application.WorkbookOpen += new Excel.AppEvents_WorkbookOpenEventHandler(App_NewWorkbook);
}
private void setRibbonControlState(ref bool isEnabled)
{
int workbookCount = Application.Windows.Count;
if (workbookCount > 1 && !isEnabled)
return;
tsFinStRibbon ribbon = Globals.Ribbons.tsFinStRibbon;
int tabCount = ribbon.Tabs.Count;
for (int i = 0; i < tabCount; i++)
{
RibbonTab tab = ribbon.Tabs[i];
int grpCount = tab.Groups.Count;
for (int j = 0; j < grpCount; j++)
{
RibbonGroup grp = tab.Groups[j];
int itCount = grp.Items.Count;
for (int k = 0; k < itCount; k++)
{
grp.Items[k].Enabled = isEnabled;
}
}
}
if (!isEnabled)
{
int paneCount = CustomTaskPanes.Count;
for (int i = 0; i < paneCount; i++)
CustomTaskPanes[i].Visible = false;
}
}
private void App_NewWorkbook(Excel.Workbook Wb)
{
// Set the ribbon
bool isEnabled = true;
setRibbonControlState(ref isEnabled);
}
private void App_WorkbookBeforeClose(Excel.Workbook Wb, ref bool Cancel)
{
bool isEnabled = (Cancel) ? false : true;
setRibbonControlState(ref isEnabled);
}
private void ThisAddIn_Shutdown(object sender, System.EventArgs e)
{
}
#region VSTO generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InternalStartup()
{
this.Startup += new System.EventHandler(ThisAddIn_Startup);
this.Shutdown += new System.EventHandler(ThisAddIn_Shutdown);
}
#endregion
}
这是完整的tsFinRibbon.cs
代码:
public partial class tsFinStRibbon
{
//static private Dictionary<string, CustomTaskPane> tsDPanes = new Dictionary<string, CustomTaskPane>();
private CustomTaskPane tsPane;
private void tsFinStRibbon_Load(object sender, RibbonUIEventArgs e)
{
// Custom task pane
Globals.ThisAddIn.CustomTaskPanes.Add(new tsDataControl(), "Data");
Globals.ThisAddIn.CustomTaskPanes.Add(new tsStControl(), "Statements");
Globals.ThisAddIn.CustomTaskPanes.Add(new tsPubControl(), "Publishing");
}
// Data task pane call
private tsDataControl setDataPane()
{
tsPane = Globals.ThisAddIn.CustomTaskPanes[0];
tsDataControl control = tsPane.Control as tsDataControl;
if (!tsPane.Visible)
{
tsPane.Width = 320;
tsPane.Visible = true;
}
return control;
}
// Statement task pane call
private tsStControl setStPane()
{
tsPane = Globals.ThisAddIn.CustomTaskPanes[1];
tsStControl control = tsPane.Control as tsStControl;
if (!tsPane.Visible)
{
tsPane.Width = 320;
tsPane.Visible = true;
}
return control;
}
// Publications task pane call
private tsPubControl setPubPane()
{
tsPane = Globals.ThisAddIn.CustomTaskPanes[2];
tsPubControl control = tsPane.Control as tsPubControl;
if (!tsPane.Visible)
{
tsPane.Width = 320;
tsPane.Visible = true;
}
return control;
}
// Balance générale
private void tsBtn1A_Click(object sender, RibbonControlEventArgs e)
{
if(Globals.ThisAddIn.CustomTaskPanes.Count != 0)
{
tsDataControl control = setDataPane();
control.selectTab(0);
}
}
// balance tiers
private void tsBtn1B_Click(object sender, RibbonControlEventArgs e)
{
if (Globals.ThisAddIn.CustomTaskPanes.Count != 0)
{
tsDataControl control = setDataPane();
control.selectTab(1);
}
}
// Calcul des états
private void tsBtn2A_Click(object sender, RibbonControlEventArgs e)
{
if (Globals.ThisAddIn.CustomTaskPanes.Count != 0)
{
tsStControl control = setStPane();
RibbonSplitButton btn = (RibbonSplitButton)sender as RibbonSplitButton;
string btnId = btn.Name;
control.selectTab(0, btnId);
}
}
// -- Calcul des états avec notes annexes
private void tsBtn2A1_Click(object sender, RibbonControlEventArgs e)
{
if(Globals.ThisAddIn.CustomTaskPanes.Count != 0)
{
tsStControl control = setStPane();
RibbonButton btn = (RibbonButton)sender as RibbonButton;
string btnId = btn.Name;
control.selectTab(0, btnId);
}
}
// -- Calcul des états sans notes annexes
private void tsBtn2A2_Click(object sender, RibbonControlEventArgs e)
{
if (Globals.ThisAddIn.CustomTaskPanes.Count != 0)
{
tsStControl control = setStPane();
RibbonButton btn = (RibbonButton)sender as RibbonButton;
string btnId = btn.Name;
control.selectTab(0, btnId);
}
}
// Bilan
private void tsBtn2B_Click(object sender, RibbonControlEventArgs e)
{
if (Globals.ThisAddIn.CustomTaskPanes.Count != 0)
{
tsStControl control = setStPane();
RibbonButton btn = (RibbonButton)sender as RibbonButton;
string btnId = btn.Name;
control.selectTab(1, btnId);
}
}
// -- Bilan actif
private void tsBtn3A_Click(object sender, RibbonControlEventArgs e)
{
if (Globals.ThisAddIn.CustomTaskPanes.Count != 0)
{
tsStControl control = setStPane();
RibbonSplitButton btn = (RibbonSplitButton)sender as RibbonSplitButton;
string btnId = btn.Name;
control.selectTab(1, btnId);
}
}
// -- Bilan Passif
private void tsBtn3B_Click(object sender, RibbonControlEventArgs e)
{
if (Globals.ThisAddIn.CustomTaskPanes.Count != 0)
{
tsStControl control = setStPane();
RibbonSplitButton btn = (RibbonSplitButton)sender as RibbonSplitButton;
string btnId = btn.Name;
control.selectTab(1, btnId);
}
}
// -- Bilan N-1
private void tsBtn3C_Click(object sender, RibbonControlEventArgs e)
{
if (Globals.ThisAddIn.CustomTaskPanes.Count != 0)
{
tsStControl control = setStPane();
RibbonSplitButton btn = (RibbonSplitButton)sender as RibbonSplitButton;
string btnId = btn.Name;
control.selectTab(1, btnId);
}
}
// -- Haut du bilan
private void tsBtn3D_Click(object sender, RibbonControlEventArgs e)
{
if (Globals.ThisAddIn.CustomTaskPanes.Count != 0)
{
tsStControl control = setStPane();
RibbonButton btn = (RibbonButton)sender as RibbonButton;
string btnId = btn.Name;
control.selectTab(1, btnId);
}
}
// -- Bas du bilan
private void tsBtn3E_Click(object sender, RibbonControlEventArgs e)
{
if (Globals.ThisAddIn.CustomTaskPanes.Count != 0)
{
tsStControl control = setStPane();
RibbonButton btn = (RibbonButton)sender as RibbonButton;
string btnId = btn.Name;
control.selectTab(1, btnId);
}
}
// Compte de résultat
private void tsBtn2C_Click(object sender, RibbonControlEventArgs e)
{
if (Globals.ThisAddIn.CustomTaskPanes.Count != 0)
{
tsStControl control = setStPane();
RibbonButton btn = (RibbonButton)sender as RibbonButton;
string btnId = btn.Name;
control.selectTab(2, btnId);
}
}
// -- Compte de résultat charges
private void tsBtn4A_Click(object sender, RibbonControlEventArgs e)
{
if (Globals.ThisAddIn.CustomTaskPanes.Count != 0)
{
tsStControl control = setStPane();
RibbonSplitButton btn = (RibbonSplitButton)sender as RibbonSplitButton;
string btnId = btn.Name;
control.selectTab(2, btnId);
}
}
private void tsBtn4B_Click(object sender, RibbonControlEventArgs e)
{
if (Globals.ThisAddIn.CustomTaskPanes.Count != 0)
{
tsStControl control = setStPane();
RibbonSplitButton btn = (RibbonSplitButton)sender as RibbonSplitButton;
string btnId = btn.Name;
control.selectTab(2, btnId);
}
}
private void tsBtn4C_Click(object sender, RibbonControlEventArgs e)
{
if (Globals.ThisAddIn.CustomTaskPanes.Count != 0)
{
tsStControl control = setStPane();
RibbonSplitButton btn = (RibbonSplitButton)sender as RibbonSplitButton;
string btnId = btn.Name;
control.selectTab(2, btnId);
}
}
private void tsBtn4D_Click(object sender, RibbonControlEventArgs e)
{
if (Globals.ThisAddIn.CustomTaskPanes.Count != 0)
{
tsStControl control = setStPane();
RibbonSplitButton btn = (RibbonSplitButton)sender as RibbonSplitButton;
string btnId = btn.Name;
control.selectTab(2, btnId);
}
}
// Flux de trésorerie
private void tsBtn2D_Click(object sender, RibbonControlEventArgs e)
{
if (Globals.ThisAddIn.CustomTaskPanes.Count != 0)
{
tsStControl control = setStPane();
RibbonButton btn = (RibbonButton)sender as RibbonButton;
string btnId = btn.Name;
control.selectTab(3, btnId);
}
}
private void tsBtn5A_Click(object sender, RibbonControlEventArgs e)
{
if (Globals.ThisAddIn.CustomTaskPanes.Count != 0)
{
tsStControl control = setStPane();
RibbonSplitButton btn = (RibbonSplitButton)sender as RibbonSplitButton;
string btnId = btn.Name;
control.selectTab(3, btnId);
}
}
private void tsBtn5B_Click(object sender, RibbonControlEventArgs e)
{
if (Globals.ThisAddIn.CustomTaskPanes.Count != 0)
{
tsStControl control = setStPane();
RibbonButton btn = (RibbonButton)sender as RibbonButton;
string btnId = btn.Name;
control.selectTab(3, btnId);
}
}
private void tsBtn5C_Click(object sender, RibbonControlEventArgs e)
{
if (Globals.ThisAddIn.CustomTaskPanes.Count != 0)
{
tsStControl control = setStPane();
RibbonSplitButton btn = (RibbonSplitButton)sender as RibbonSplitButton;
string btnId = btn.Name;
control.selectTab(3, btnId);
}
}
private void tsBtn5D_Click(object sender, RibbonControlEventArgs e)
{
if (Globals.ThisAddIn.CustomTaskPanes.Count != 0)
{
tsStControl control = setStPane();
RibbonSplitButton btn = (RibbonSplitButton)sender as RibbonSplitButton;
string btnId = btn.Name;
control.selectTab(3, btnId);
}
}
// Annexes
private void tsBtn6A_Click(object sender, RibbonControlEventArgs e)
{
if (Globals.ThisAddIn.CustomTaskPanes.Count != 0)
{
tsStControl control = setStPane();
RibbonSplitButton btn = (RibbonSplitButton)sender as RibbonSplitButton;
string btnId = btn.Name;
control.selectTab(4, btnId);
}
}
private void tsBtn7A_Click(object sender, RibbonControlEventArgs e)
{
if (Globals.ThisAddIn.CustomTaskPanes.Count != 0)
{
tsPubControl control = setPubPane();
control.selectTab(0);
}
}
private void tsBtn7B_Click(object sender, RibbonControlEventArgs e)
{
if (Globals.ThisAddIn.CustomTaskPanes.Count != 0)
{
tsPubControl control = setPubPane();
control.selectTab(1);
}
}
private void tsBtn7C_Click(object sender, RibbonControlEventArgs e)
{
if (Globals.ThisAddIn.CustomTaskPanes.Count != 0)
{
tsPubControl control = setPubPane();
control.selectTab(2);
}
}
}
我更改了自定义功能区选项卡的load事件处理程序. tspane
属性的使用无关紧要.自定义功能区选项卡的加载事件处理程序将创建三个自定义任务窗格.它们每个都与一组特定的功能区按钮相关.单击组中的按钮时,将调用相应的任务窗格,并激活任务窗格中的相应tabControl.
I changed a bit the load event handler of the custom ribbon tab. The use of the tspane
property was irrelevant. The load event handler of the custom ribbon tab creates three custom tasks panes. Each of them are related to a specific group of ribbon buttons. When a button in a group is clicked, the appropriate task pane is called and the appropriate tabControl in the task pane is activated.
正如我之前所说,当我打开Excel时,当单击功能区按钮时,只有初始工作簿会返回自定义任务窗格.
As I said before, when I open Excel, only the initial workbook return the custom task pane when I click on a ribbon button.
我还注意到,当我打开Excel,创建/打开第二个工作簿并单击自定义功能区选项卡上的功能区按钮时,初始工作簿上可见的任务窗格会做出反应并激活正确的选项卡或任务窗格.
I also noticed that when I open Excel, create/open a second workbook and click on a ribbon button of the custom ribbon tab, the task pane that is visible on the initial workbook reacts and activates the correct tab or task pane.
推荐答案
我终于明白了.必须为每个需要在其上出现的窗口创建自定义任务窗格".我以为自定义任务窗格"是绑定到应用程序的,而不是绑定到任何特定的工作簿的,所以我只创建了其中的3个.
I figured it out finally. The Custom Task Panes must be created for each window it needs to appear on. As I thought the Custom Task Panes was bound to the application and not any specific Workbook, I just created the 3 of them only once.
因此,我创建了一个Dictionary来跟踪我创建的任务窗格及其在CustomTaskPaneCollection中的位置,以便在切换Excel窗口时可以调用/或创建(如果需要)任何任务窗格.这是关键代码:
So, I created a Dictionary to keep track of the Task Panes I creates and its position in the CustomTaskPaneCollection so I can recall / or create (if necessary) any Task Pane when I switch Excel windows. Here are the key codes:
private CustomTaskPane tsPane;
private int Wn;
private Dictionary<string, int> dict;
private void tsFinStRibbon_Load(object sender, RibbonUIEventArgs e)
{
// Create a dictionary of indexes
dict = new Dictionary<string, int>();
}
// Données
private tsDataControl setDataPane()
{
// Initialize the window ID and pane name
Wn = Globals.ThisAddIn.Application.Hwnd;
string paneName = "Data" + Wn.ToString();
// Check if the CTP already exists and create it otherwise
if (!dict.ContainsKey(paneName))
{
tsPane = Globals.ThisAddIn.CustomTaskPanes.Add(new tsDataControl(), paneName);
dict.Add(paneName, Globals.ThisAddIn.CustomTaskPanes.Count - 1);
}
else
{
tsPane = Globals.ThisAddIn.CustomTaskPanes[dict[paneName]];
}
// Get the tab control
tsDataControl control = tsPane.Control as tsDataControl;
if (!tsPane.Visible)
{
tsPane.Width = 320;
tsPane.Visible = true;
}
return control;
}
// Etats
private tsStControl setStPane()
{
// Initialize the window ID and pane name
Wn = Globals.ThisAddIn.Application.Hwnd;
string paneName = "Statement" + Wn.ToString();
// Check if the CTP already exists and create it otherwise
if (!dict.ContainsKey(paneName))
{
tsPane = Globals.ThisAddIn.CustomTaskPanes.Add(new tsStControl(), "Statement");
dict.Add(paneName, Globals.ThisAddIn.CustomTaskPanes.Count - 1);
}
else
{
tsPane = Globals.ThisAddIn.CustomTaskPanes[dict[paneName]];
}
// Get the tab control
tsStControl control = tsPane.Control as tsStControl;
// Display the pane
if (!tsPane.Visible)
{
tsPane.Width = 320;
tsPane.Visible = true;
}
return control;
}
// Publications
private tsPubControl setPubPane()
{
// Initialize the window ID and pane name
Wn = Globals.ThisAddIn.Application.Hwnd;
string paneName = "Publishing" + Wn.ToString();
// Check if the CTP already exists and create it otherwise
if (!dict.ContainsKey(paneName))
{
tsPane = Globals.ThisAddIn.CustomTaskPanes.Add(new tsPubControl(), paneName);
dict.Add(paneName, Globals.ThisAddIn.CustomTaskPanes.Count - 1);
}
else
{
tsPane = Globals.ThisAddIn.CustomTaskPanes[dict[paneName]];
}
// Get the tab control
tsPubControl control = tsPane.Control as tsPubControl;
// Display the pane
if (!tsPane.Visible)
{
tsPane.Width = 320;
tsPane.Visible = true;
}
return control;
}
谢谢!
这篇关于Excel VSTO自定义任务窗格的可用性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!