Excel催化剂开源第5波-任务窗格在OFFICE2013中新建文档不能同步显示问题解决

2021-08-19 14:57:22 浏览数 (1)

在OFFICE2013及之后,使用了单文档界面技术,不同于以往版本可以共享任务空格、功能区。所以当开发任务窗格时,需要考虑到每一个工作薄都关联一个任务窗格。

背景介绍

单文档界面摘录官方定义如下: 对 Excel 2013 中的单文档界面 (SDI) 进行更改对可编程性具有一定影响。SDI 意味着每个工作簿都将有其自己的顶级应用程序窗口,并将有自己的相应功能区。

带来的好处是不同工作薄可以精细控制不同的显示,例如工作薄A,显示功能区Tab1,工作薄B显示功能区Tab2,区分对待不同文档所使用的功能。

带来的不便之处就是要每个文档都要考虑关联对应的界面,特别是任务窗格。

具体代码实现

Excel催化剂插件也大量使用了任务窗格,为了让用户在作配置信息时,可以更灵活,不必每次都弹出一个窗体来配置,只有需要配置时,才转到任务窗格中配置,否则保留默认的配置,并且默认配置可以让用户在任务窗格上查看。

所以用了任务窗格,需要做版本兼容性,即区分Excel2013及之后的版本的SDI特性。

下面截取关键代码,以Excel工作薄的工作表导航功能为例,作简单解释

工作表导航任务窗格

先初始化字典变量

代码语言:javascript复制
        private static void InialTaskPanel()
        {
            Utilities.TaskPanelUtility.CustomTaskPanesOfWorksheetNavigation = new Dictionary<int, Microsoft.Office.Tools.CustomTaskPane>();
            Utilities.TaskPanelUtility.UscWorksheetNavigations = new Dictionary<int, UscWorksheetNavigation>();
        }

根据不同版本的Excel启用不同方法

代码语言:javascript复制
        private void tgbShowActionPanel_Click(object sender, RibbonControlEventArgs e)
        {
            RibbonToggleButton tgb = sender as RibbonToggleButton;
            try
            {
                if (Single.Parse(Common.ExcelApp.Version) >= 15)
                {

                    WorksheetNavigate.ShowCustomTaskPanelOfWorksheetNavigationOfExcel2013(tgb.Checked);
                }
                else
                {
                    WorksheetNavigate.ShowCustomTaskPanelOfWorksheetNavigationOfExcel2010(tgb.Checked);
                }
                //将工作表导航的显示状态保存起来
                Properties.Settings.Default.IsPaneVisible = tgb.Checked;
                Properties.Settings.Default.Save();
            }
            catch (Exception ex)
            {
                Common.OutMsgError(ex);
            }
        }

重点是2013版的方法,关键之处是拿到当前的活动窗体的句柄,通过字典查找是否已经创建过,没创建就新建,新建完要把它句柄存入到字典中。

代码语言:javascript复制
        public static void ShowCustomTaskPanelOfWorksheetNavigationOfExcel2013(bool isPaneVisible)
        {
            int hwndCustomTaskPane = Common.ExcelApp.ActiveWindow.Hwnd;
            Microsoft.Office.Tools.CustomTaskPane activeCustomTaskPane;
          Utilities.TaskPanelUtility.CustomTaskPanesOfWorksheetNavigation.TryGetValue(hwndCustomTaskPane, out activeCustomTaskPane);
            if (activeCustomTaskPane == null)
            {
                UscWorksheetNavigation uscWorksheetNavigation = new UscWorksheetNavigation();
                activeCustomTaskPane = Globals.ThisAddIn.CustomTaskPanes.Add(uscWorksheetNavigation, "工作表导航", Globals.ThisAddIn.Application.ActiveWindow);
                activeCustomTaskPane.DockPosition = Office.MsoCTPDockPosition.msoCTPDockPositionLeft;
                activeCustomTaskPane.Width = 300;

                activeCustomTaskPane.VisibleChanged  = ActiveCustomTaskPane_VisibleChanged;
                activeCustomTaskPane.Visible = isPaneVisible;
                Utilities.TaskPanelUtility.CustomTaskPanesOfWorksheetNavigation.Add(hwndCustomTaskPane, activeCustomTaskPane);
                Utilities.TaskPanelUtility.UscWorksheetNavigations.Add(hwndCustomTaskPane, uscWorksheetNavigation);
            }
            else
            {
                activeCustomTaskPane.Visible = isPaneVisible;
                if (isPaneVisible)
                {
                    Utilities.TaskPanelUtility.UscWorksheetNavigations[hwndCustomTaskPane].ReLoadWorksheetName();
                }
            }
        }

因工作表导航,每切换一次工作薄,都要更新下工作表清单,所以订阅了一个窗体切换事件,其他场景可能不必这样做,只需订阅个打开文件事件即可。

代码语言:javascript复制
        private void ExcelApp_WindowActivate(Excel.Workbook Wb, Excel.Window Wn)
        {
            try
            {
                if (Common.ExcelApp.ActiveWorkbook.ProtectStructure == false)
                {
                    bool isPaneVisible = Properties.Settings.Default.IsPaneVisible;

                    if (Single.Parse(Common.ExcelApp.Version) >= 15)
                    {
                        int hwndCustomTaskPane = this.Application.ActiveWindow.Hwnd;
                        WorksheetNavigate.ShowCustomTaskPanelOfWorksheetNavigationOfExcel2013(isPaneVisible);
                    }
                    else
                    {
                        WorksheetNavigate.ShowCustomTaskPanelOfWorksheetNavigationOfExcel2010(isPaneVisible);
                    }
                }
            }
            catch (Exception)
            {

            }

        }

其他的非关键代码,自己把握如何写就行,笔者写代码也有限,只能抛砖引玉了。

结语

通过直接的源代码讲解,希望对Excel开发的朋友们可以带来一些帮助,具体原理之外的东西,可自由发挥。

0 人点赞