近日的一系列工作是做網(wǎng)站的營(yíng)運(yùn)維護(hù),因此做了大量的支持工具。有Excel中寫VBA的,也有直接C#做的工具。有時(shí)需要在C#中執(zhí)行Excel VBA宏,甚至有時(shí)還需要在執(zhí)行了VBA宏之后,獲取返回值再進(jìn)行相應(yīng)的處理。為了使用方便,我寫了一個(gè)執(zhí)行Excel VBA宏的幫助類 。放在博客里做個(gè)備份也希望對(duì)有類似需求的朋友有所幫助。
幫助類僅提供了一個(gè)方法:RunExcelMacro
參數(shù)說(shuō)明:
string excelFilePath Excel文件路徑
string macroName 宏名稱
object[] parameters 宏參數(shù)組
out object rtnValue 宏返回值
bool isShowExcel 執(zhí)行時(shí)是否顯示Excel
補(bǔ)充說(shuō)明:VBA宏需如下圖寫在模塊中,才能被此方法識(shí)別。寫在ThisWorkBook中不能被識(shí)別。
執(zhí)行Excel VBA宏幫助類,注釋比較詳細(xì),不再累贅代碼過(guò)程。最核心部分其實(shí)就是通過(guò)反射方式調(diào)用Excel VBA宏,oBook.Save()這句話也很重要,否則即使執(zhí)行了VBA宏調(diào)用,也不會(huì)保存Excel更改后的內(nèi)容:
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 /// 執(zhí)行Excel VBA宏幫助類
12 /// </summary>
13 public class ExcelMacroHelper
14 {
15 /// <summary>
16 /// 執(zhí)行Excel中的宏
17 /// </summary>
18 /// <param name="excelFilePath">Excel文件路徑</param>
19 /// <param name="macroName">宏名稱</param>
20 /// <param name="parameters">宏參數(shù)組</param>
21 /// <param name="rtnValue">宏返回值</param>
22 /// <param name="isShowExcel">執(zhí)行時(shí)是否顯示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 檢查入?yún)?/span>
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("請(qǐng)輸入宏的名稱");
45 }
46
47 #endregion
48
49 #region 調(diào)用宏處理
50
51 // 準(zhǔn)備打開(kāi)Excel文件時(shí)的缺省參數(shù)對(duì)象
52 object oMissing = System.Reflection.Missing.Value;
53
54 // 根據(jù)參數(shù)組是否為空,準(zhǔn)備參數(shù)組對(duì)象
55 object[] paraObjects;
56
57 if (parameters == null)
58 {
59 paraObjects = new object[] { macroName };
60 }
61 else
62 {
63 // 宏參數(shù)組長(zhǎng)度
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 // 創(chuàng)建Excel對(duì)象示例
76 Excel.ApplicationClass oExcel = new Excel.ApplicationClass();
77
78 // 判斷是否要求執(zhí)行時(shí)Excel可見(jiàn)
79 if (isShowExcel)
80 {
81 // 使創(chuàng)建的對(duì)象可見(jiàn)
82 oExcel.Visible = true;
83 }
84
85 // 創(chuàng)建Workbooks對(duì)象
86 Excel.Workbooks oBooks = oExcel.Workbooks;
87
88 // 創(chuàng)建Workbook對(duì)象
89 Excel._Workbook oBook = null;
90
91 // 打開(kāi)指定的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 // 執(zhí)行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 釋放對(duì)象
122
123 // 釋放Workbook對(duì)象
124 System.Runtime.InteropServices.Marshal.ReleaseComObject(oBook);
125 oBook = null;
126
127 // 釋放Workbooks對(duì)象
128 System.Runtime.InteropServices.Marshal.ReleaseComObject(oBooks);
129 oBooks = null;
130
131 // 關(guān)閉Excel
132 oExcel.Quit();
133
134 // 釋放Excel對(duì)象
135 System.Runtime.InteropServices.Marshal.ReleaseComObject(oExcel);
136 oExcel = null;
137
138 // 調(diào)用垃圾回收
139 GC.Collect();
140
141 #endregion
142 }
143 catch (Exception ex)
144 {
145 throw ex;
146 }
147 }
148
149 /// <summary>
150 /// 執(zhí)行宏
151 /// </summary>
152 /// <param name="oApp">Excel對(duì)象</param>
153 /// <param name="oRunArgs">參數(shù)(第一個(gè)參數(shù)為指定宏名稱,后面為指定宏的參數(shù)值)</param>
154 /// <returns>宏返回值</returns>
155 private object RunMacro(object oApp, object[] oRunArgs)
156 {
157 try
158 {
159 // 聲明一個(gè)返回對(duì)象
160 object objRtn;
161
162 // 反射方式執(zhí)行宏
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
示例三個(gè)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
對(duì)應(yīng)的三個(gè)使用方法
1 不帶參數(shù)的宏調(diào)用(兼演示執(zhí)行過(guò)程顯示Excel文件)
2 帶參數(shù)的宏調(diào)用(兼演示執(zhí)行過(guò)程不顯示Excel文件)
3 有返回值的宏調(diào)用
1 private void btnExe_Click(object sender, EventArgs e)
2 {
3 try
4 {
5 // 返回對(duì)象
6 object objRtn = new object();
7
8 // 獲得一個(gè)ExcelMacroHelper對(duì)象
9 ExcelMacroHelper excelMacroHelper = new ExcelMacroHelper();
10
11 // 執(zhí)行指定Excel中的宏,執(zhí)行時(shí)顯示Excel
12 excelMacroHelper.RunExcelMacro(
13 @"E:\csharp_study\DoVBAMacro\test.xls",
14 "getTime2",
15 new Object[] { "現(xiàn)在時(shí)刻" },
16 out objRtn,
17 true
18 );
19
20 // 執(zhí)行指定Excel中的宏,執(zhí)行時(shí)不顯示Excel
21 excelMacroHelper.RunExcelMacro(
22 @"E:\csharp_study\DoVBAMacro\test.xls",
23 "getTime2",
24 new Object[] { "現(xiàn)在時(shí)刻" },
25 out objRtn,
26 false
27 );
28
29 // 執(zhí)行指定Excel中的宏,執(zhí)行時(shí)顯示Excel,有返回值
30 excelMacroHelper.RunExcelMacro(
31 @"E:\csharp_study\DoVBAMacro\test.xls",
32 "getTime3",
33 new Object[] { "現(xiàn)在時(shí)刻" },
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
示例工程下載
Tag標(biāo)簽:
c#,
反射,
VBA,
Excel,
宏