Excel VSTO自定义任务窗格的可用性

时间:2019-02-27 14:50:30

标签: c# excel vsto

我写了一个Excel应用程序级VSTO。但是有些我不明白。我创建的自定义功能区选项卡在应用程序级别可用,这意味着所有打开的工作簿。

我使用 Ribbon Designer 创建了功能区选项卡,并通过setRibbonControlState文件中的函数ThisAddIn.cs调用了它的一个实例。该函数由我从ThisAddIn_startup处理的3个事件调用:

((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);

在此级别上,一切正常。

然后,我创建了3个用户选项卡控件(当然每个课程都有一个.cs文件)以显示在3个CustomTaskPanes中。我在功能区选项卡的load事件处理程序中创建了3个CustomTaskPanes,并编写了一些函数来显示相应的任务窗格和内部控件的相应选项卡。这是ribbon.cs的部分代码,显示了我如何创建和显示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时,只能从初始电子表格访问内部控件中的相应任务窗格和选项卡。我打开或创建的任何其他电子表格都提供功能区选项卡,但是当我单击其任何按钮时,自定义任务窗格不会显示。

我试图从ThisAddIn.cs文件创建任务窗格,并且有效地创建了它们,但是只有当我单击初始电子表格中的功能区时,它们才会做出反应。

在我的阅读中,我找不到有效地将功能区附加到任务窗格以使其正常运行的方法。

有人知道如何解决吗?

谢谢。

编辑

这是完整的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。

正如我之前所说,当我打开Excel时,当单击功能区按钮时,只有初始工作簿会返回自定义任务窗格。

我还注意到,当我打开Excel,创建/打开第二个工作簿并单击自定义功能区选项卡的功能区按钮时,初始工作簿上可见的任务窗格会做出反应并激活正确的选项卡或任务窗格。

1 个答案:

答案 0 :(得分:0)

我终于明白了。必须为每个需要在其上出现的窗口创建自定义任务窗格。我以为“自定义任务窗格”是绑定到应用程序的,而不是绑定到任何特定的工作簿的,所以我只创建了其中的3个。

因此,我创建了一个Dictionary来跟踪创建的任务窗格及其在CustomTaskPaneCollection中的位置,以便在切换Excel窗口时可以调用/或创建(如有必要)任何任务窗格。以下是关键代码:

    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;
    }

谢谢!