Excel是微软办公套装软件的一个重要的组成部分,它可以进行各种数据的处理、统计分析和辅助决策操作,广泛地应用于管理、统计财经、金融等众多领域。(另外,Excel还是伦敦一所会展中心的名称)。.NET可以创建Excel Add-In对Excel进行功能扩展,这些扩展的功能包括自定义用户函数,自定义UI,与数据库进行数据交互等。
一 主要的Excel开发方式
1 VBA
VBA是一种Visual Basic的宏语言,它是最早的Office提供定制化的一种解决方案,VBA是VB的一个子集,和Visual Basic不同,VBA是一种宿主型语言,无论是专业的开发人员,还是刚入门的非开发人员,都可以利用VBA完成简单或复杂的需求。
2 Excel 插件
Excel Addin,就像Visual Studio外接插件一样,也可以使用一些技术为Office开发一些插件。对VBA的一些问题,一些专业的开发人员,可以使用 VisualBasic或者VisualC++等工具来引用Office的一些dll,来针对Office进行开发。开发的时候将dll注册为com组 件,并在注册表里面进行注册,这样就可以在Excel里直接调用这些插件。
3 VSTO(Office 的 Visual Studio 工具)
VSTO主要是对Office的一些dll进行了.NET封装,使得我们可以使用.NET上的语言来方便的对Office的一些方法进行调用。所 以,Office开发跨入了一个新的时代,开发人员可以使用更加高级的语言和熟悉的技术来更容易的进行Office开发。 对于企业及的应用和开发,VSTO或许是首要选择,他极大地扩展了Office应用程序的能力,使用.NET平台支持的编程语言,能够直接访问.NET上面众多的类库。具有较好的安全机制。简化了Office插件的开发和部署。
4 XLL
XLL是Excel的一种外接应用程序,他使用C和C++开发,程序通过调用Excel暴漏的C接口来实现扩展功能。这种方式开发的应用程序效率高,但是难度大,对开发者自身的要求较高。开源项目Excel-DNA就是使用XLL技术开发的,能够帮助.NET 开发人员来极大地简化RTD函数,同步、异步UDF函数的编写和开发。
5 OpenXML
如果用户没有安装Excel应用程序,或者在服务器端需要动态生成Excel文件的时候。我们可能需要直接读取或者生成Excel文件,这种情况下,如果要对Excel文件进行各种定制化开发的话,建议使用OpenXML。NPOI开源项目可以直接读写Excel文件,而且兼容多个版本。
二 使用Excel Add-In构建扩展
开发环境: 操作系统为Windows Server 2008R2 x64;Excel为Excel 2010 x64;开发工具为Visual Studio 2012旗舰版x64;数据库为SQL Server 2008R2 x64.
1 程序结构
用Visual Studio 2012新建一个ExcelAddInDemo的Excel Add-In项目,并添加若干文件,程序结构如下图:
其中,RibbonAddIn可以定制2010的UI面板,SqlHelper.cs是一个简单的数据库访问帮助类,UClog.cs,UCPaneLeft.cs,UCTaskGrid.cs,UCTaskPane.cs都为添加的自定义控件,并通过程序添加到EXCEL界面中.运行起来的界面如下:
程序可以通过在Excel界面中输入ID,First,Last,Email的值(对应标签的后一个单元格),单击用户列表面板上的保存按钮,将数据保存到数据库中.
2 RibbonAddIn设计
我们通过RibbonAddIn.cs给Excel的Ribbon添加了一个名为CUMT的插件.RibbonAddIn面板可以通过工具条控件方便的拖放到设计界面上.RibbonAddIn.cs的属性设置如下图所示:
后台代码如下:
1 使用 系统;
2 使用 System.Collections.Generic;
3 使用 System.Linq;
4 使用 System.Text;
5 使用 Microsoft.Office.Tools.Ribbon;
6
7 命名空间 ExcelAddInDemo
8 {
9 公共 部分 类 RibbonAddIn
10 {
11
12 private void RibbonAddIn_Load( 对象 发送者,RibbonUIEventArgs e)
13 {
14
15 }
16
17 private void btnAbout_Click( 对象 发送者,RibbonControlEventArgs e)
18 {
19 System.Windows.Forms.MessageBox.Show( “ JackWangCUMT! ” );
20 }
21
22 private void btnShow_Click( 对象 发送者,RibbonControlEventArgs e)
23 {
24 if (Globals.ThisAddIn._MyCustomTaskPane != null )
25 {
26 Globals.ThisAddIn._MyCustomTaskPane.Visible = true ;
27 }
28 }
29
30 private void btnHide_Click( 对象 发送者,RibbonControlEventArgs e)
31 {
32 if (Globals.ThisAddIn._MyCustomTaskPane != null )
33 {
34 Globals.ThisAddIn._MyCustomTaskPane.Visible = false ;
35 }
36 }
37 }
38 }
3 ThisAddIn逻辑编写
1 使用 系统;
2 使用 System.Collections.Generic;
3 使用 System.Linq;
4 使用 System.Text;
5 使用 System.Xml.Linq;
6 使用 Excel = Microsoft.Office.Interop.Excel;
7 命名空间 ExcelAddInDemo
8 {
9 使用 Microsoft.Office.Tools;
10 公共 部分 类 ThisAddIn
11 {
12 公共 CustomTaskPane _MyCustomTaskPane = null ;
13
14 private void ThisAddIn_Startup( 对象 发送者,System.EventArgs e)
15 {
16 UCTaskPane taskPane = new UCTaskPane();
17 _MyCustomTaskPane = this .CustomTaskPanes.Add(taskPane, " 我的任务面板 " );
18 _MyCustomTaskPane.Width = 30 ; // height 有问题,此处width ==height
19 _MyCustomTaskPane.Visible = true ;
20 _MyCustomTaskPane.DockPosition = Microsoft.Office.Core.MsoCTPDockPosition.msoCTPDockPositionTop;
21
22 UCPaneLeft panLeft = new UCPaneLeft();
23 _MyCustomTaskPane = this .CustomTaskPanes.Add(panLeft, " 组织 " );
24 _MyCustomTaskPane.Width = 200 ;
25 _MyCustomTaskPane.Visible = true ;
26 _MyCustomTaskPane.DockPosition = Microsoft.Office.Core.MsoCTPDockPosition.msoCTPDockPositionLeft;
27
28 UCTaskGrid panRight = new UCTaskGrid();
29 _MyCustomTaskPane = this .CustomTaskPanes.Add(panRight, " 用户列表 " );
30 _MyCustomTaskPane.Width = 200 ;
31 _MyCustomTaskPane.Visible = true ;
32 _MyCustomTaskPane.DockPosition = Microsoft.Office.Core.MsoCTPDockPosition.msoCTPDockPositionRight;
33
34 UCLog panLog = new UCLog();
35 _MyCustomTaskPane = this .CustomTaskPanes.Add(panLog, " 日志列表 " );
36 _MyCustomTaskPane.Width = 60 ;
37 _MyCustomTaskPane.Visible = true ;
38 _MyCustomTaskPane.DockPosition = Microsoft.Office.Core.MsoCTPDockPosition.msoCTPDockPositionBottom;
39
40 // 挂钩工作簿打开事件
41 // 这是因为运行此方法时,Office 并不总是准备好文档
42 this .Application.WorkbookActivate += Application_WorkbookActivate;
43 // 测试
44 // this.Application.SheetSelectionChange += Application_SheetSelectionChange;
45 }
46
47 void Application_SheetSelectionChange( object Sh, Excel.Range Target)
48 {
49 如果 ( 这个 .Application != null )
50 {
51 this .Application.Caption = this .Application.ActiveCell.Address.ToString(); // 1 澳元
52 // + this.Application.ActiveCell.AddressLocal.ToString(); // 1 澳元
53 // this.Application.ActiveCell.Formula = "=sum(1+2)";
54
55 }
56 }
57
58 无效 Application_WorkbookActivate(Excel.Workbook Wb)
59 {
60 // using Microsoft.Office.Tools.Excel 和 using Microsoft.Office.Interop.Excel 等,容易重新调整
61 // 字符串路径 = this.Application.ActiveWorkbook.FullName;
62 Excel._Worksheet ws = (Excel._Worksheet) this .Application.ActiveWorkbook.ActiveSheet;
63 ws.Cells[ 2 , 2 ] = " ID2 " ;
64 // 如何设置只读等有待研究
65 int r= 2 ,c= 2 ;
66 // ((Excel.Range)ws.Cells[r, c]).NumberFormat = format;
67 ((Excel.Range)ws.Cells[r, c]).Value2 = " ID " ;
68 ((Excel.Range)ws.Cells[r, c]).Interior.Color = System.Drawing。 ColorTranslator.ToOle(System.Drawing.Color.Red);
69 // ((Excel.Range)ws.Cells[r, c]).Style.Name = "Normal";
70 ((Excel.Range)ws.Cells[r, c]).Style.Font.Bold = true ;
71
72 #region 格式
73 ((Microsoft.Office.Interop.Excel.Range)ws.get_Range( " A2 " , " E10 " )).Font.Bold = true ;
74 ((Microsoft.Office.Interop.Excel.Range)ws.get_Range( " A2 " , " E10 " )).Font.Italic = true ;
75 ((Microsoft.Office.Interop.Excel.Range)ws.get_Range( " A2 " , " E10 " )).Font.Color = System.Drawing.Color.FromArgb( 96 , 32 ,