近日的一系列工作是做网站的营运维护,因此做了大量的支持工具。有Excel中写VBA的,也有直接C#做的工具。有时需要在C#中执行Excel VBA宏,甚至有时还需要在执行了VBA宏之后,获取返回值再进行相应的处理。为了使用方便,我写了一个执行Excel VBA宏的帮助类 。放在博客里做个备份也希望对有类似需求的朋友有所帮助。
帮助类仅提供了一个方法:RunExcelMacro
参数说明:
string excelFilePath Excel文件路径
string macroName 宏名称
object[] parameters 宏参数组
out object rtnValue 宏返回值
bool isShowExcel 执行时是否显示Excel
补充说明:VBA宏需如下图写在模块中,才能被此方法识别。写在ThisWorkBook中不能被识别。
执行Excel VBA宏帮助类,注释比较详细,不再累赘代码过程。最核心部分其实就是通过反射方式调用Excel VBA宏,oBook.Save()这句话也很重要,否则即使执行了VBA宏调用,也不会保存Excel更改后的内容:
1
using
System;
2 using System.Collections.Generic;
3 using System.Text;
4 using Excel = Microsoft.Office.Interop.Excel;
5 using Microsoft.Office.Core;
6 using System.IO;
7
8 namespace DoVBAMacro
9 {
10 /// <summary>
11 /// 执行Excel VBA宏帮助类
12 /// </summary>
13 public class ExcelMacroHelper
14 {
15 /// <summary>
16 /// 执行Excel中的宏
17 /// </summary>
18 /// <param name="excelFilePath"> Excel文件路径 </param>
19 /// <param name="macroName"> 宏名称 </param>
20 /// <param name="parameters"> 宏参数组 </param>
21 /// <param name="rtnValue"> 宏返回值 </param>
22 /// <param name="isShowExcel"> 执行时是否显示Excel </param>
23 public void RunExcelMacro(
24 string excelFilePath,
25 string macroName,
26 object [] parameters,
27 out object rtnValue,
28 bool isShowExcel
29 )
30 {
31 try
32 {
33 #region 检查入参
34
35 // 检查文件是否存在
36 if ( ! File.Exists(excelFilePath))
37 {
38 throw new System.Exception(excelFilePath + " 文件不存在 " );
39 }
40
41 // 检查是否输入宏名称
42 if ( string .IsNullOrEmpty(macroName))
43 {
44 throw new System.Exception( " 请输入宏的名称 " );
45 }
46
47 #endregion
48
49 #region 调用宏处理
50
51 // 准备打开Excel文件时的缺省参数对象
52 object oMissing = System.Reflection.Missing.Value;
53
54 // 根据参数组是否为空,准备参数组对象
55 object [] paraObjects;
56
57 if (parameters == null )
58 {
59 paraObjects = new object [] { macroName };
60 }
61 else
62 {
63 // 宏参数组长度
64 int paraLength = parameters.Length;
65
66 paraObjects = new object [paraLength + 1 ];
67
68 paraObjects[ 0 ] = macroName;
69 for ( int i = 0 ; i < paraLength; i ++ )
70 {
71 paraObjects[i + 1 ] = parameters[i];
72 }
73 }
74
75 // 创建Excel对象示例
76 Excel.ApplicationClass oExcel = new Excel.ApplicationClass();
77
78 // 判断是否要求执行时Excel可见
79 if (isShowExcel)
80 {
81 // 使创建的对象可见
82 oExcel.Visible = true ;
83 }
84
85 // 创建Workbooks对象
86 Excel.Workbooks oBooks = oExcel.Workbooks;
87
88 // 创建Workbook对象
89 Excel._Workbook oBook = null ;
90
91 // 打开指定的Excel文件
92 oBook = oBooks.Open(
93 excelFilePath,
94 oMissing,
95 oMissing,
96 oMissing,
97 oMissing,
98 oMissing,
99 oMissing,
100 oMissing,
101 oMissing,
102 oMissing,
103 oMissing,
104 oMissing,
105 oMissing,
106 oMissing,
107 oMissing
108 );
109
110 // 执行Excel中的宏
111 rtnValue = this .RunMacro(oExcel, paraObjects);
112
113 // 保存更改
114 oBook.Save();
115
116 // 退出Workbook
117 oBook.Close( false , oMissing, oMissing);
118
119 #endregion
120
121 #region 释放对象
122
123 // 释放Workbook对象
124 System.Runtime.InteropServices.Marshal.ReleaseComObject(oBook);
125 oBook = null ;
126
127 // 释放Workbooks对象
128 System.Runtime.InteropServices.Marshal.ReleaseComObject(oBooks);
129 oBooks = null ;
130
131 // 关闭Excel
132 oExcel.Quit();
133
134 // 释放Excel对象
135 System.Runtime.InteropServices.Marshal.ReleaseComObject(oExcel);
136 oExcel = null ;
137
138 // 调用垃圾回收
139 GC.Collect();
140
141 #endregion
142 }
143 catch (Exception ex)
144 {
145 throw ex;
146 }
147 }
148
149 /// <summary>
150 /// 执行宏
151 /// </summary>
152 /// <param name="oApp"> Excel对象 </param>
153 /// <param name="oRunArgs"> 参数(第一个参数为指定宏名称,后面为指定宏的参数值) </param>
154 /// <returns> 宏返回值 </returns>
155 private object RunMacro( object oApp, object [] oRunArgs)
156 {
157 try
158 {
159 // 声明一个返回对象
160 object objRtn;
161
162 // 反射方式执行宏
163 objRtn = oApp.GetType().InvokeMember(
164 " Run " ,
165 System.Reflection.BindingFlags.Default |
166 System.Reflection.BindingFlags.InvokeMethod,
167 null ,
168 oApp,
169 oRunArgs
170 );
171
172 // 返回值
173 return objRtn;
174
175 }
176 catch (Exception ex)
177 {
178 // 如果有底层异常,抛出底层异常
179 if (ex.InnerException.Message.ToString().Length > 0 )
180 {
181 throw ex.InnerException;
182 }
183 else
184 {
185 throw ex;
186 }
187 }
188 }
189 }
190 }
191
2 using System.Collections.Generic;
3 using System.Text;
4 using Excel = Microsoft.Office.Interop.Excel;
5 using Microsoft.Office.Core;
6 using System.IO;
7
8 namespace DoVBAMacro
9 {
10 /// <summary>
11 /// 执行Excel VBA宏帮助类
12 /// </summary>
13 public class ExcelMacroHelper
14 {
15 /// <summary>
16 /// 执行Excel中的宏
17 /// </summary>
18 /// <param name="excelFilePath"> Excel文件路径 </param>
19 /// <param name="macroName"> 宏名称 </param>
20 /// <param name="parameters"> 宏参数组 </param>
21 /// <param name="rtnValue"> 宏返回值 </param>
22 /// <param name="isShowExcel"> 执行时是否显示Excel </param>
23 public void RunExcelMacro(
24 string excelFilePath,
25 string macroName,
26 object [] parameters,
27 out object rtnValue,
28 bool isShowExcel
29 )
30 {
31 try
32 {
33 #region 检查入参
34
35 // 检查文件是否存在
36 if ( ! File.Exists(excelFilePath))
37 {
38 throw new System.Exception(excelFilePath + " 文件不存在 " );
39 }
40
41 // 检查是否输入宏名称
42 if ( string .IsNullOrEmpty(macroName))
43 {
44 throw new System.Exception( " 请输入宏的名称 " );
45 }
46
47 #endregion
48
49 #region 调用宏处理
50
51 // 准备打开Excel文件时的缺省参数对象
52 object oMissing = System.Reflection.Missing.Value;
53
54 // 根据参数组是否为空,准备参数组对象
55 object [] paraObjects;
56
57 if (parameters == null )
58 {
59 paraObjects = new object [] { macroName };
60 }
61 else
62 {
63 // 宏参数组长度
64 int paraLength = parameters.Length;
65
66 paraObjects = new object [paraLength + 1 ];
67
68 paraObjects[ 0 ] = macroName;
69 for ( int i = 0 ; i < paraLength; i ++ )
70 {
71 paraObjects[i + 1 ] = parameters[i];
72 }
73 }
74
75 // 创建Excel对象示例
76 Excel.ApplicationClass oExcel = new Excel.ApplicationClass();
77
78 // 判断是否要求执行时Excel可见
79 if (isShowExcel)
80 {
81 // 使创建的对象可见
82 oExcel.Visible = true ;
83 }
84
85 // 创建Workbooks对象
86 Excel.Workbooks oBooks = oExcel.Workbooks;
87
88 // 创建Workbook对象
89 Excel._Workbook oBook = null ;
90
91 // 打开指定的Excel文件
92 oBook = oBooks.Open(
93 excelFilePath,
94 oMissing,
95 oMissing,
96 oMissing,
97 oMissing,
98 oMissing,
99 oMissing,
100 oMissing,
101 oMissing,
102 oMissing,
103 oMissing,
104 oMissing,
105 oMissing,
106 oMissing,
107 oMissing
108 );
109
110 // 执行Excel中的宏
111 rtnValue = this .RunMacro(oExcel, paraObjects);
112
113 // 保存更改
114 oBook.Save();
115
116 // 退出Workbook
117 oBook.Close( false , oMissing, oMissing);
118
119 #endregion
120
121 #region 释放对象
122
123 // 释放Workbook对象
124 System.Runtime.InteropServices.Marshal.ReleaseComObject(oBook);
125 oBook = null ;
126
127 // 释放Workbooks对象
128 System.Runtime.InteropServices.Marshal.ReleaseComObject(oBooks);
129 oBooks = null ;
130
131 // 关闭Excel
132 oExcel.Quit();
133
134 // 释放Excel对象
135 System.Runtime.InteropServices.Marshal.ReleaseComObject(oExcel);
136 oExcel = null ;
137
138 // 调用垃圾回收
139 GC.Collect();
140
141 #endregion
142 }
143 catch (Exception ex)
144 {
145 throw ex;
146 }
147 }
148
149 /// <summary>
150 /// 执行宏
151 /// </summary>
152 /// <param name="oApp"> Excel对象 </param>
153 /// <param name="oRunArgs"> 参数(第一个参数为指定宏名称,后面为指定宏的参数值) </param>
154 /// <returns> 宏返回值 </returns>
155 private object RunMacro( object oApp, object [] oRunArgs)
156 {
157 try
158 {
159 // 声明一个返回对象
160 object objRtn;
161
162 // 反射方式执行宏
163 objRtn = oApp.GetType().InvokeMember(
164 " Run " ,
165 System.Reflection.BindingFlags.Default |
166 System.Reflection.BindingFlags.InvokeMethod,
167 null ,
168 oApp,
169 oRunArgs
170 );
171
172 // 返回值
173 return objRtn;
174
175 }
176 catch (Exception ex)
177 {
178 // 如果有底层异常,抛出底层异常
179 if (ex.InnerException.Message.ToString().Length > 0 )
180 {
181 throw ex.InnerException;
182 }
183 else
184 {
185 throw ex;
186 }
187 }
188 }
189 }
190 }
191
示例三个VBA宏方法:
1
Sub
getTime()
2
3 Sheet1.Cells( 1 , 1 ) = Now
4
5 End Sub
6
7
8 Sub getTime2(title As String )
9
10 Sheet1.Cells( 2 , 1 ) = title & " : " & Now
11
12 End Sub
13
14 Function getTime3(title As String ) As String
15
16 getTime3 = title & " : " & Now
17
18 End Function
19
2
3 Sheet1.Cells( 1 , 1 ) = Now
4
5 End Sub
6
7
8 Sub getTime2(title As String )
9
10 Sheet1.Cells( 2 , 1 ) = title & " : " & Now
11
12 End Sub
13
14 Function getTime3(title As String ) As String
15
16 getTime3 = title & " : " & Now
17
18 End Function
19
对应的三个使用方法
1 不带参数的宏调用(兼演示执行过程显示Excel文件)
2 带参数的宏调用(兼演示执行过程不显示Excel文件)
3 有返回值的宏调用
1
private
void
btnExe_Click(
object
sender, EventArgs e)
2 {
3 try
4 {
5 // 返回对象
6 object objRtn = new object ();
7
8 // 获得一个ExcelMacroHelper对象
9 ExcelMacroHelper excelMacroHelper = new ExcelMacroHelper();
10
11 // 执行指定Excel中的宏,执行时显示Excel
12 excelMacroHelper.RunExcelMacro(
13 @" E:\csharp_study\DoVBAMacro\test.xls " ,
14 " getTime2 " ,
15 new Object[] { " 现在时刻 " },
16 out objRtn,
17 true
18 );
19
20 // 执行指定Excel中的宏,执行时不显示Excel
21 excelMacroHelper.RunExcelMacro(
22 @" E:\csharp_study\DoVBAMacro\test.xls " ,
23 " getTime2 " ,
24 new Object[] { " 现在时刻 " },
25 out objRtn,
26 false
27 );
28
29 // 执行指定Excel中的宏,执行时显示Excel,有返回值
30 excelMacroHelper.RunExcelMacro(
31 @" E:\csharp_study\DoVBAMacro\test.xls " ,
32 " getTime3 " ,
33 new Object[] { " 现在时刻 " },
34 out objRtn,
35 true
36 );
37
38 MessageBox.Show(( string )objRtn);
39
40 }
41 catch (System.Exception ex)
42 {
43 MessageBox.Show(ex.Message);
44 }
45 }
2 {
3 try
4 {
5 // 返回对象
6 object objRtn = new object ();
7
8 // 获得一个ExcelMacroHelper对象
9 ExcelMacroHelper excelMacroHelper = new ExcelMacroHelper();
10
11 // 执行指定Excel中的宏,执行时显示Excel
12 excelMacroHelper.RunExcelMacro(
13 @" E:\csharp_study\DoVBAMacro\test.xls " ,
14 " getTime2 " ,
15 new Object[] { " 现在时刻 " },
16 out objRtn,
17 true
18 );
19
20 // 执行指定Excel中的宏,执行时不显示Excel
21 excelMacroHelper.RunExcelMacro(
22 @" E:\csharp_study\DoVBAMacro\test.xls " ,
23 " getTime2 " ,
24 new Object[] { " 现在时刻 " },
25 out objRtn,
26 false
27 );
28
29 // 执行指定Excel中的宏,执行时显示Excel,有返回值
30 excelMacroHelper.RunExcelMacro(
31 @" E:\csharp_study\DoVBAMacro\test.xls " ,
32 " getTime3 " ,
33 new Object[] { " 现在时刻 " },
34 out objRtn,
35 true
36 );
37
38 MessageBox.Show(( string )objRtn);
39
40 }
41 catch (System.Exception ex)
42 {
43 MessageBox.Show(ex.Message);
44 }
45 }
帮助类需添加引用:Microsoft Excel 11.0 Object Library