C#调用Excel VBA宏
近日的一系列工作是做网站的营运维护,因此做了大量的支持工具。有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 }
C#调用Excel VBA宏的更多相关文章
- C#调用Excel VBA宏[转载]
原文地址:https://www.cnblogs.com/heekui/archive/2008/03/30/1129355.html 近日的一系列工作是做网站的营运维护,因此做了大量的支持工具.有E ...
- [转]C#调用Excel VBA宏
[转载自]http://www.shangxueba.com/jingyan/95031.html 附上一段原创常用代码 计算列标题字符串 Function CalcColumn(ByVal c As ...
- Excel VBA宏 链接服务器 上传和下载数据
首先说明以下. 第一: 下面的 “ _" 也就是 空格下划线 在VBA中表示换行的意思:& 表示链接连个字符串的操作,注意 & 的前后是否需要空格 第二: 如果链接服务器,服 ...
- C#调用Excel宏
using System; using Excel = Microsoft.Office.Interop.Excel; namespace WindowsFormsApplication1 { /// ...
- 功能区按钮调用Excel、PowerPoint、Word中的VBA宏:RunMacro
功能区按钮调用Excel.PowerPoint.Word中的VBA宏:RunMacro 众所周知,Excel.PPT.Word文档或加载宏文件中可以写很多过程和函数,调试的过程中当然可以按F8或F5直 ...
- Excel VBA(宏):添加宏
写在前面: .编写宏,打开VBA,双击ThisWorkbook对当前工作薄进行编写宏:双击Sheet1,对整个sheet编写宏: 或者创建模块,在模块里,编写.调试代码. 打开VBA的方法见第一讲,结 ...
- Excel VBA入门(七)注释、宏按钮及错误处理
系统性的知识前面已经讲完,从本章开始,本系列教程涉及的将会是一些相对凌散的内容. 1. 注释 代码注释是一件利人利己的事,为了方便自己在代码需要更新修改时,依然能够快速地看懂自己完的每一行代码到底是什 ...
- Excel 导出指定行为txt文件(VBA,宏)
要从Excel 多个sheet内导出指定行为txt文件,懒得用C#了,写个VBA宏 Sub Export() Dim FileName As Variant Dim Sep As String Dim ...
- 使用vbs调用excel中的宏
使用vbs打开excel文件,并且传递参数调用excel中的macro,自动化完成excel文件的制作. Set oExcel = createobject("Excel.Applicati ...
随机推荐
- 精品手游《里奥的财富》高清版逆向移植家用机与PC平台(转)
冒险动作游戏<里奥的财富>于去年10月登陆移动平台,曾荣获App Store“年度优秀游戏”.开发商宣布将推出其HD版本,近期会陆续登陆PS4.PC.MAC.Xbox One平台. 由瑞典 ...
- 我的格斗梦——张龙海(R.J)谈游戏动画师职业(转)
编者按:他是一个生在东北,祖藉却是韩国的年轻人.从小生性好动的他觉得上课 学习十分枯燥,所以高中没毕业便辍学在家.但他仍是一个喜欢动漫.游戏的年轻人,因为热爱所以他用父母给的钱开始了求学之路,在之后的 ...
- STL六大组件之——适配器代表大会
适配器也是一种常用的设计模式: 将一个类的接口转换为另一个类的接口,使得原本因接口不兼容而不能合作的两个类可以一起运作.STL提供三种适配器:改变容器接口的容器适配器.改变迭代器接口的迭代器适配器以及 ...
- 数据结构(12) -- 图的邻接矩阵的DFS和BFS
//////////////////////////////////////////////////////// //图的邻接矩阵的DFS和BFS ////////////////////////// ...
- ASP.NET MVC 常用内置验证特性 简介
1.[Required] : 必须输入 [Required(ErrorMessage = "请输入用户名")] 2.[StringLength] : 限制字符串长度 [String ...
- lego blocks
1.题目描述 https://www.hackerrank.com/challenges/lego-blocks 2.解法分析 这题乍看一下觉得应该可以用动态规划来做,但是却死活想不到最优子结构,在网 ...
- 《The Google File System》论文阅读笔记——GFS设计原理
一.设计预期 设计预期往往针对系统的应用场景,是系统在不同选择间做balance的重要依据,对于理解GFS在系统设计时为何做出现有的决策至关重要.所以我们应重点关注: 失效是常态 主要针对大文件 读操 ...
- linux下生成 SSH 公钥,用于GitHub
ssh-keygen -t rsa -C <email> 参见 https://help.github.com/articles/generating-ssh-keys/ Then add ...
- 【转】jsp页面中jstl标签详解
原文地址: JSLT标签库,是日常开发经常使用的,也是众多标签中性能最好的.把常用的内容,放在这里备份一份,随用随查.尽量做到不用查,就可以随手就可以写出来.这算是Java程序员的基本功吧,一定要扎实 ...
- python知识点(07-08)
python: 循环else: while true: if x>1: print() break else: print() 文件循环: for line in open(‘test.txt’ ...