1.本例開發(fā)了一個(gè)Excel 文檔管理的插件,基于VS2012 和Excel2010,先上效果圖
2.技術(shù)原理:使用Excel提供的自定義任務(wù)面板即CTP技術(shù)以及Ribbon菜單實(shí)現(xiàn)
1.先新增一個(gè)Ribbon 菜單,本人給的名字是UserRibbon,就是開始菜單的第一個(gè)文檔管理的按鈕,控制是否打開文檔管理的那個(gè)自定義任務(wù)面板
2.增加一個(gè)UserControl,里面加上TreeView控件,來顯示三種EXcel文檔(當(dāng)前打開文檔,經(jīng)常使用文檔,最近使用文檔)
3.加載任務(wù)面板代碼段
<pre name="code" class="csharp">using System; using System.Collections.Generic; 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; 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(); 有點(diǎn)問題先不控制 ExcelApp = Globals.ThisAddIn.Application; docExplorer = new DocExplorer(); Globals.ThisAddIn.Application.WorkbookOpen += Application_WorkbookOpen; DocManageTaskPane = Globals.ThisAddIn.CustomTaskPanes.Add(docExplorer, "文檔瀏覽器"); ShowDocManageTaskPane(MsoCTPDockPosition.msoCTPDockPositionLeft); 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; /// 設(shè)計(jì)器支持所需的方法 - 不要 /// 使用代碼編輯器修改此方法的內(nèi)容。 private void InternalStartup() this.Startup += new System.EventHandler(ThisAddIn_Startup); this.Shutdown += new System.EventHandler(ThisAddIn_Shutdown); public partial class ThisAddIn [DllImport("User32.dll ")] private static extern bool ShowWindowAsync(IntPtr hWnd, int cmdShow); private void SingleInstanceCheck() 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) Process.GetProcessById(Process_min_id).Kill(); Process_min_id = processes[i].Id; ShowWindowAsync(Process.GetProcessById(Process_min_id).MainWindowHandle, 1);
4 操作文檔管理代碼段
using System.Collections.Generic; using System.ComponentModel; using System.Windows.Forms; using Excel=Microsoft.Office.Interop.Excel; using System.Collections; public partial class DocExplorer : UserControl Excel.Application ExcelApp; Excel.Workbooks ExcelWorkBooks; Hashtable ht_common = new Hashtable(); //保存常用的excel Hashtable ht_cuureet = new Hashtable();//保存當(dāng)時(shí)的excel TreeNode root = new TreeNode();//根節(jié)點(diǎn) TreeNode common_root = new TreeNode();//常用根節(jié)點(diǎn) TreeNode current_root = new TreeNode();//當(dāng)前根節(jié)點(diǎn) TreeNode recent_root = new TreeNode();//最近使用根節(jié)點(diǎn) ExcelApp = Globals.ThisAddIn.Application; ExcelWorkBooks = ExcelApp.Workbooks; public void SetFileList(string filePath, string fileName) 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) //創(chuàng)建Excel控件對(duì)象 Boolean docExists = false; if (e.Node.Level == 2 && e.Button==MouseButtons.Left)//左鍵單擊葉子節(jié)點(diǎn)打開文件 Excelpath = treeView_FileList.SelectedNode.Name; foreach (Excel._Workbook wb in ExcelWorkBooks) if (Excelpath == wb.FullName) if (File.Exists(Excelpath)) //監(jiān)聽了excel 打開事件,當(dāng)前使用文檔統(tǒng)一在打開事件里面處理 ExcelWorkBooks.Open(Excelpath); if (!current_root.IsExpanded) current_root.ExpandAll(); MessageBox.Show("文件不存在!"); private void treeView_FileList_NodeMouseDoubleClick(object sender, TreeNodeMouseClickEventArgs e) if (e.Node.Parent == current_root && e.Node.Level==2)//雙擊打開文件則關(guān)閉 foreach (Excel._Workbook wb in ExcelWorkBooks) if (e.Node.Name == wb.FullName) current_root.Nodes.Remove(e.Node); private void TreeViewInit() current_root.Text = "當(dāng)前打開文檔"; common_root.Text = "經(jīng)常使用文檔"; recent_root.Text = "最近使用文檔"; treeView_FileList.Nodes.Add(root); root.Nodes.Add(current_root); root.Nodes.Add(common_root); root.Nodes.Add(recent_root); private void LoadCommonFiles() int firstIndex, lastIndex; Key = Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Office\Excel\Addins\OfficeDocM"); xmlPath = Key.GetValue("Manifest").ToString(); firstIndex=xmlPath.IndexOf(":")+4; lastIndex=xmlPath.LastIndexOf("/"); xmlPath=xmlPath.Substring(firstIndex, lastIndex - firstIndex); xmlPath = xmlPath + @"\CustExcels.xml"; XmlDocument xmlDoc = new XmlDocument(); if (File.Exists(xmlPath)) XmlReaderSettings settings = new XmlReaderSettings(); settings.IgnoreComments = true; XmlNode ExcelsNode = xmlDoc.SelectSingleNode("Excels"); // 得到根節(jié)點(diǎn)的所有子節(jié)點(diǎn) XmlNodeList ExcelsNodeList = ExcelsNode.ChildNodes; foreach (XmlNode xnitem in ExcelsNodeList) TreeNode chldNode = new TreeNode(); // 將節(jié)點(diǎn)轉(zhuǎn)換為元素,便于得到節(jié)點(diǎn)的屬性值 XmlElement excelList = (XmlElement)xnitem; // 得到excel節(jié)點(diǎn)的所有子節(jié)點(diǎn) XmlNodeList xnl0 = excelList.ChildNodes; docName = xnl0.Item(0).InnerText; docPath = xnl0.Item(1).InnerText; chldNode.Name = docPath + @"\" + docName; chldNode.ForeColor = Color.Purple; common_root.Nodes.Add(chldNode); if (!common_root.IsExpanded) 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) /*因?yàn)閱螕暨x中的還是上次的節(jié)點(diǎn),那么在第一次加載上次的節(jié)點(diǎn)還是null的 *所以使用單擊打開這個(gè)事件是必不可少的*/ 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關(guān)鍵點(diǎn)說明
1.本例中使用到了一個(gè)XML文件作為配置文件,保存經(jīng)常使用的文檔信息,有一個(gè)問題就是,沒辦法確定這個(gè)文件的路徑,因?yàn)椴恢烙脩魰?huì)把這個(gè)插件安裝在哪里,各種方法試就是不行,突然靈機(jī)一動(dòng),Excel 怎么加載插件的,原來在注冊(cè)表,果然如此 就有了下面一段代碼(路徑里包含一些其他東西 就特別處理了一下)
int firstIndex, lastIndex; Key = Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Office\Excel\Addins\OfficeDocM"); xmlPath = Key.GetValue("Manifest").ToString(); firstIndex=xmlPath.IndexOf(":")+4; lastIndex=xmlPath.LastIndexOf("/"); xmlPath=xmlPath.Substring(firstIndex, lastIndex - firstIndex); xmlPath = xmlPath + @"\CustExcels.xml";
2.Ribbon 菜單位置的確定
圖1 圖2
 2.1如果自己的菜單想獨(dú)立(與office本生的菜單如開始,插入等 平級(jí) Ribbon的ControlIDType 就選擇Custom,若想其作為一個(gè)字菜單就選Office,并通過OfficeId指定其屬于哪個(gè)菜單,如 圖1 )
2.2 子菜單位置確定,如 圖2 關(guān)鍵屬性 Position
2.3 每個(gè)Office 菜單Id 見 office 菜單名稱
|