近日的一系列工作是做网站的营运维护,因此做了大量的支持工具。有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
示例三个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
对应的三个使用方法
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
}
帮助类需添加引用:
Microsoft Excel 11.0 Object Library
示例工程下载
使用Excel调用ABAP系统的函数
效果:在excel里创建一个按钮,开发一些VB script,可以连接指定的ABAP系统并执行系统里的ABAP function module。