Excel插件开发

1.本例开发了一个Excel 文档管理的插件,基于VS2012 和Excel2010,先上效果图

2.技术原理:使用Excel提供的自定义任务面板即CTP技术以及Ribbon菜单实现

1.先新增一个Ribbon 菜单,本人给的名字是UserRibbon,就是开始菜单的第一个文档管理的按钮,控制是否打开文档管理的那个自定义任务面板

2.增加一个UserControl,里面加上TreeView控件,来显示三种EXcel文档(当前打开文档,经常使用文档,最近使用文档)


3.加载任务面板代码段

<pre name="code" class="csharp">using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using Excel = Microsoft.Office.Interop.Excel;
using Office = Microsoft.Office.Core;
using Microsoft.Office.Tools.Excel;
using Microsoft.Office.Core;
using System.Diagnostics;
using System.Runtime.InteropServices;


namespace OfficeDocM
{
    public partial class ThisAddIn
    {
        
        // 定义一个任务窗体 
        internal Microsoft.Office.Tools.CustomTaskPane DocManageTaskPane;
        internal DocExplorer docExplorer;
        internal Excel.Application ExcelApp;

        private void ThisAddIn_Startup(object sender, System.EventArgs e)
        {
           //SingleInstanceCheck(); 有点问题先不控制
            Init(); 
        }
        private void Init()
        {
            //初始化
            ExcelApp = Globals.ThisAddIn.Application;

            //实例化文档浏览器窗口
            docExplorer = new DocExplorer();

            //注册Excel打开事件
            Globals.ThisAddIn.Application.WorkbookOpen += Application_WorkbookOpen;

            //加载自定义面板
            DocManageTaskPane = Globals.ThisAddIn.CustomTaskPanes.Add(docExplorer, "文档浏览器");
            ShowDocManageTaskPane(MsoCTPDockPosition.msoCTPDockPositionLeft);
        }
        //处理Excel打开事件
        private void Application_WorkbookOpen(Excel.Workbook Wb)
        {
            docExplorer.SetFileList(Wb.Path, ExcelApp.ActiveWorkbook.Name);
        }

        private void ThisAddIn_Shutdown(object sender, System.EventArgs e)
        {
        }

        public void ShowDocManageTaskPane(MsoCTPDockPosition postion = MsoCTPDockPosition.msoCTPDockPositionLeft)
        {
            // 使任务窗体可见 
            DocManageTaskPane.Visible = true;
            DocManageTaskPane.DockPosition = postion;
        }
        public void HideDocManageTaskPane()
        {
            // 使任务窗体不可见 
            DocManageTaskPane.Visible = false;
        }

        #region VSTO 生成的代码

        /// <summary>
        /// 设计器支持所需的方法 - 不要
        /// 使用代码编辑器修改此方法的内容。
        /// </summary>
        private void InternalStartup()
        {
            this.Startup += new System.EventHandler(ThisAddIn_Startup);
            this.Shutdown += new System.EventHandler(ThisAddIn_Shutdown);
        }
        #endregion
    }


    //非托管代码部分(引用Win32API)
    public partial class ThisAddIn
    {
        [DllImport("User32.dll ")]
        private static extern bool ShowWindowAsync(IntPtr hWnd, int cmdShow);

        //单实例检查
        private  void SingleInstanceCheck()
        {
            int Process_min_id; 
            Process[] processes = Process.GetProcessesByName("EXCEL");
            Process_min_id = processes[0].Id;
            //杀死其他进程
            if (processes.Length > 1)
            {
                for (int i = 1; i < processes.Length; i++)
                {
                    if (Process_min_id < processes[i].Id)
                        processes[i].Kill();
                    else
                    {
                        Process.GetProcessById(Process_min_id).Kill();
                        Process_min_id = processes[i].Id;
                    }
                }
            }
            //显示最开始的进程
            ShowWindowAsync(Process.GetProcessById(Process_min_id).MainWindowHandle, 1);
        }
    }
}
4 操作文档管理代码段
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Excel=Microsoft.Office.Interop.Excel;
using System.IO;
using System.Xml;
using System.Collections;
using System.Reflection;
using Microsoft.Win32;

namespace OfficeDocM
{
    public partial class DocExplorer : UserControl
    {
        Excel.Application ExcelApp;
        Excel.Workbooks ExcelWorkBooks;
        Hashtable ht_common = new Hashtable(); //保存常用的excel
        Hashtable ht_cuureet = new Hashtable();//保存当时的excel

        TreeNode root = new TreeNode();//根节点
        TreeNode common_root = new TreeNode();//常用根节点
        TreeNode current_root = new TreeNode();//当前根节点
        TreeNode recent_root = new TreeNode();//最近使用根节点

        public DocExplorer()
        {
            InitializeComponent();
            Init();
        }
        public void Init()
        {
            ExcelApp = Globals.ThisAddIn.Application;
            ExcelWorkBooks = ExcelApp.Workbooks;
            //树根初始化
            TreeViewInit();
            //加载XML常用文件配置
            LoadCommonFiles();
            //加载最近使用文件 
            LoadRecentFiles();
        }


        public void SetFileList(string filePath, string fileName)
        {
            string fileFullPath;
            fileFullPath = filePath + @"\" + fileName;
            if (File.Exists(fileFullPath))
            {    
             TreeNode chldNode = new TreeNode();
             chldNode.Name = fileFullPath;
             chldNode.Text = fileName;
             current_root.Nodes.Add(chldNode);
             chldNode.ForeColor = Color.Red;
             if (!current_root.IsExpanded)
                current_root.ExpandAll();
            }
        }

        //单击打开文件
        private void treeView_FileList_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e)
        {
            //创建Excel控件对象
           
            string Excelpath;
            Boolean docExists = false;
            if (e.Node.Level == 2 && e.Button==MouseButtons.Left)//左键单击叶子节点打开文件
            {
                Excelpath = treeView_FileList.SelectedNode.Name;
               
                foreach (Excel._Workbook wb in ExcelWorkBooks)
                {
                    if (Excelpath == wb.FullName)
                    {
                        wb.Activate();
                        docExists = true;
                        break;
                    }
                }
                if (!docExists)
                {
                    if (File.Exists(Excelpath))
                    {
                       //监听了excel 打开事件,当前使用文档统一在打开事件里面处理
                        ExcelWorkBooks.Open(Excelpath);
                        if (!current_root.IsExpanded)
                            current_root.ExpandAll();
                    }
                    else
                        MessageBox.Show("文件不存在!");
                }
            }
        }
        //双击关闭文件
        private void treeView_FileList_NodeMouseDoubleClick(object sender, TreeNodeMouseClickEventArgs e)
        {
            if (e.Node.Parent == current_root && e.Node.Level==2)//双击打开文件则关闭
            {
                foreach (Excel._Workbook wb in ExcelWorkBooks)
                {
                    if (e.Node.Name == wb.FullName)
                    {
                        wb.Close();
                        current_root.Nodes.Remove(e.Node);
                        break;
                    }
                }
            }
        }
        private  void TreeViewInit()
        {
            root.Text = "文档列表";
            current_root.Text = "当前打开文档";
            common_root.Text = "经常使用文档";
            recent_root.Text = "最近使用文档";
            treeView_FileList.Nodes.Add(root);
            root.Nodes.Add(current_root);
            root.Nodes.Add(common_root);
            root.Nodes.Add(recent_root);
            if (!root.IsExpanded) 
            {
                root.Expand();
            }
        }
        private void LoadCommonFiles()
        {
            string xmlPath;
            int firstIndex, lastIndex;
            RegistryKey Key;
            Key = Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Office\Excel\Addins\OfficeDocM");
            xmlPath = Key.GetValue("Manifest").ToString();
            Key.Close();
           
            firstIndex=xmlPath.IndexOf(":")+4;
            lastIndex=xmlPath.LastIndexOf("/");
            xmlPath=xmlPath.Substring(firstIndex, lastIndex - firstIndex);
            xmlPath = xmlPath + @"\CustExcels.xml";
            //加载XML
            XmlDocument xmlDoc = new XmlDocument();
            if (File.Exists(xmlPath))
            {
                xmlDoc.Load(xmlPath);
                //忽略注释内容
                XmlReaderSettings settings = new XmlReaderSettings();
                settings.IgnoreComments = true;
                //得到根节点
                XmlNode ExcelsNode = xmlDoc.SelectSingleNode("Excels");
                // 得到根节点的所有子节点
                XmlNodeList ExcelsNodeList = ExcelsNode.ChildNodes;

                foreach (XmlNode xnitem in ExcelsNodeList)
                {
                    TreeNode chldNode = new TreeNode();
                    string docPath, docName;
                    // 将节点转换为元素,便于得到节点的属性值
                    XmlElement excelList = (XmlElement)xnitem;
                    // 得到excel节点的所有子节点
                    XmlNodeList xnl0 = excelList.ChildNodes;
                    docName = xnl0.Item(0).InnerText;
                    docPath = xnl0.Item(1).InnerText;

                    chldNode.Name = docPath + @"\" + docName;
                    chldNode.Text = docName;
                    chldNode.ForeColor = Color.Purple;
                    common_root.Nodes.Add(chldNode);
                }
                if (!common_root.IsExpanded)
                    common_root.ExpandAll();
            }
            else
            {
                Log my = new Log(@"D:\log.txt", FileMode.Create);
                my.Writeln(DateTime.Now.ToLocalTime().ToString()+"["+xmlPath+"]");
            }
        }
        private void LoadRecentFiles()
        {
            string fileFullPath,fileName;
            for (int i = 1; i <= ExcelApp.RecentFiles.Count; i++)
            {
                fileFullPath=ExcelApp.RecentFiles.get_Item(i).Name;
                if (File.Exists(fileFullPath))
                {
                    fileName = System.IO.Path.GetFileName(fileFullPath);
                    TreeNode chldNode = new TreeNode();
                    chldNode.Name = fileFullPath;
                    chldNode.Text = fileName;
                    recent_root.Nodes.Add(chldNode);
                    chldNode.ForeColor = Color.SteelBlue;
                    if (!recent_root.IsExpanded)
                        recent_root.ExpandAll();
                }
            }
        
        }
        /*因为单击选中的还是上次的节点,那么在第一次加载上次的节点还是null的
         *所以使用单击打开这个事件是必不可少的*/
        private void treeView_FileList_MouseDown(object sender, MouseEventArgs e)
        {
            if ((sender as TreeView) != null)
            {
                treeView_FileList.SelectedNode = treeView_FileList.GetNodeAt(e.X, e.Y);
            }
        }
       
    }
}

5关键点说明

1.本例中使用到了一个XML文件作为配置文件,保存经常使用的文档信息,有一个问题就是,没办法确定这个文件的路径,因为不知道用户会把这个插件安装在哪里,各种方法试就是不行,突然灵机一动,Excel 怎么加载插件的,原来在注册表,果然如此 就有了下面一段代码(路径里包含一些其他东西 就特别处理了一下)

 string xmlPath;
 int firstIndex, lastIndex;
 RegistryKey Key;
 Key = Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Office\Excel\Addins\OfficeDocM");
 xmlPath = Key.GetValue("Manifest").ToString();
 Key.Close();
           
 firstIndex=xmlPath.IndexOf(":")+4;
 lastIndex=xmlPath.LastIndexOf("/");
 xmlPath=xmlPath.Substring(firstIndex, lastIndex - firstIndex);
 xmlPath = xmlPath + @"\CustExcels.xml";
2.Ribbon  菜单位置的确定

                                                图1                                                                                             图2

   
2.1如果自己的菜单想独立(与office本生的菜单如开始,插入等 平级 Ribbon的ControlIDType 就选择Custom,若想其作为一个字菜单就选Office,并通过OfficeId指定其属于哪个菜单,如 图1 )

2.2 子菜单位置确定,如 图2 关键属性 Position 

2.3 每个Office 菜单Id 见  office 菜单名称

 

  • 3
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Excel模板软件开发模块是指通过编写代码和使用相关工具,对Excel软件进行定制化开发的一部分。该模块通常有以下几个主要功能: 1. 模板设计:软件开发模块可用于设计Excel模板,包括创建表格、定义数据格式、设置样式和布局等。开发人员可以根据用户需求和业务逻辑,自定义Excel模板的结构和功能。 2. 数据处理:模板软件开发模块可以对Excel中的数据进行处理,如数据导入、数据清洗、数据转换等。通过编写代码,开发人员可以实现数据的自动化抽取、整理和分析,提高工作效率和数据准确性。 3. 功能扩展:软件开发模块还可以对Excel软件进行功能扩展,通过编写宏(Macro)或使用插件(Add-in)等方式,实现更多的功能和特性。例如,可以开发自定义函数、自动化报表生成、图表绘制等特定功能,以满足用户的特定需求。 4. 与外部系统集成:模板软件开发模块还可以与外部系统进行集成,通过编写代码和使用相关API,实现Excel与其他业务系统的数据交互。这样可以实现数据的无缝传输和共享,提高数据的准确性和一致性。 总的来说,Excel模板软件开发模块是用于对Excel软件进行个性化定制和功能扩展的开发环节。通过编写代码和使用相关的工具,开发人员可以为用户提供更加灵活、高效、定制化的Excel应用。 ### 回答2: Excel模板是一种预先设计好的电子表格文件,用于存储和处理数据。通过Excel模板,用户可以快速创建具有特定功能的电子表格,例如财务报表、项目计划、销售数据分析等。Excel模板可以节省用户的时间和精力,提高工作效率。 在软件开发中,Excel模板模块可以提供以下功能: 1. 模板设计:开发人员可以根据用户需求和业务规则,设计和创建定制化的Excel模板。这个过程通常包括确定表格结构、字段设置、公式编写等。通过模板设计,可以确保模板具有灵活性和可扩展性,以满足不同的业务需求。 2. 数据导入:Excel模板模块可以支持从外部数据源导入数据到模板中。这样用户就可以将现有的数据快速导入到Excel模板中,方便后续的数据处理和分析。导入数据的方式可以包括手动输入、数据连接、数据导入等。 3. 数据处理:Excel模板可以通过预设的公式和函数,对导入的数据进行自动计算和处理。例如,可以进行数值加减、求平均值、排序等操作。这样用户可以在不需要编写复杂程序的情况下,实现数据的自动处理和分析。 4. 数据输出:Excel模板模块可以支持将处理后的数据输出到其他系统。例如,可以将数据导出为CSV、PDF等格式,以方便在其他系统中使用。同时,也可以将Excel模板作为报表模板,生成可视化和易读的报告。 总之,Excel模板模块在软件开发中是一个非常有用的功能,可以帮助用户快速创建和处理 Excel 数据,提高工作效率和准确性。同时,通过定制化的模板设计,可以满足不同业务需求,使Excel模板成为一个强大的数据处理工具。 ### 回答3: Excel模板软件开发模块是指在Excel软件中开发的模块,用于定制化开发一些特定功能的应用程序。 Excel模板软件开发模块主要包括以下几个方面: 1. VBA编程:VBA是Visual Basic for Applications的缩写,是一种嵌入在Excel中的编程语言。通过使用VBA编程,可以为Excel模板添加各种自定义功能,如宏命令、自动计算、自动填充等。 2. 数据处理:Excel模板软件开发模块可以用于数据处理,例如创建复杂的数据分析模型、数据清洗和转化、数据的导入和导出等。通过使用Excel的数据处理功能,可以帮助用户快速方便地进行数据分析和决策。 3. 用户界面设计:Excel模板软件开发模块可以根据用户需求进行界面设计,使用户可以通过操作按钮、下拉列表、单选框等方式与模板进行交互。用户界面设计的目的是让用户能够方便地操作Excel模板,并且使界面美观、易懂。 4. 数据源连接:Excel模板软件开发模块可以通过连接不同的数据源,如数据库、网上数据源等,来获取数据。通过数据源连接,可以实现实时数据更新和数据的自动导入,提高Excel模板的数据质量和准确性。 5. 报表生成:Excel模板软件开发模块可以根据用户需求,生成各种类型的报表。用户可以自定义报表的格式、样式和内容,使报表的生成符合用户的需求和要求。 综上所述,Excel模板软件开发模块是通过在Excel软件中进行VBA编程,实现数据处理、用户界面设计、数据源连接和报表生成等功能的模块。通过使用这些模块,可以为用户定制化开发出各种特定功能的Excel模板应用程序。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值