首页 > 编程语言 >执行VBA的C#底层引擎编写

执行VBA的C#底层引擎编写

时间:2023-05-23 10:44:48浏览次数:30  
标签:vba string C# Excel VBA System var vbaCode 底层

VBA执行分几种:

using System;
using Excel = Microsoft.Office.Interop.Excel;
using System.IO;
using System.Diagnostics;
using Microsoft.Vbe.Interop;
using Microsoft.Office.Interop.Excel;
using System.Text;
using VBIDE = Microsoft.Vbe.Interop;


namespace ExcelVBA
{
    public class VBAHelper
    {
        /// <summary>
        /// 执行Excel中的宏
        /// </summary>
        /// <param name="excelFilePath">Excel文件路径</param>
        /// <param name="macroName">宏名称</param>
        /// <param name="parameters">宏参数组</param>
        /// <param name="rtnValue">宏返回值</param>
        /// <param name="isShowExcel">执行时是否显示Excel</param>
        public void RunExcelMacro(
                                            string excelFilePath,
                                            string macroName,
                                            object[] parameters,
                                            out object rtnValue,
                                            bool isShowExcel
                                        )
        {
            try
            {
                #region 检查入参

                // 检查文件是否存在
                if (!File.Exists(excelFilePath))
                {
                    throw new System.Exception(excelFilePath + " 文件不存在");
                }

                // 检查是否输入宏名称
                if (string.IsNullOrEmpty(macroName))
                {
                    throw new System.Exception("请输入宏的名称");
                }

                #endregion

                #region 调用宏处理

                // 准备打开Excel文件时的缺省参数对象
                object oMissing = System.Reflection.Missing.Value;

                // 根据参数组是否为空,准备参数组对象
                object[] paraObjects;

                if (parameters == null)
                {
                    paraObjects = new object[] { macroName };
                }
                else
                {
                    // 宏参数组长度
                    int paraLength = parameters.Length;

                    paraObjects = new object[paraLength + 1];

                    paraObjects[0] = macroName;
                    for (int i = 0; i < paraLength; i++)
                    {
                        paraObjects[i + 1] = parameters[i];
                    }
                }

                // 创建Excel对象示例
                Excel.ApplicationClass oExcel = new Excel.ApplicationClass();

                // 判断是否要求执行时Excel可见
                if (isShowExcel)
                {
                    // 使创建的对象可见
                    oExcel.Visible = true;
                }

                // 创建Workbooks对象
                Excel.Workbooks oBooks = oExcel.Workbooks;

                // 创建Workbook对象
                Excel._Workbook oBook = null;

                // 打开指定的Excel文件
                oBook = oBooks.Open(
                                        excelFilePath,
                                        oMissing,
                                        oMissing,
                                        oMissing,
                                        oMissing,
                                        oMissing,
                                        oMissing,
                                        oMissing,
                                        oMissing,
                                        oMissing,
                                        oMissing,
                                        oMissing,
                                        oMissing,
                                        oMissing,
                                        oMissing
                                   );

                // 执行Excel中的宏
                rtnValue = this.RunMacro(oExcel, paraObjects);

                // 保存更改
                oBook.Save();

                // 退出Workbook
                oBook.Close(false, oMissing, oMissing);

                #endregion

                #region 释放对象

                // 释放Workbook对象
                System.Runtime.InteropServices.Marshal.ReleaseComObject(oBook);
                oBook = null;

                // 释放Workbooks对象
                System.Runtime.InteropServices.Marshal.ReleaseComObject(oBooks);
                oBooks = null;

                // 关闭Excel
                oExcel.Quit();

                // 释放Excel对象
                System.Runtime.InteropServices.Marshal.ReleaseComObject(oExcel);
                oExcel = null;

                // 调用垃圾回收
                GC.Collect();

                #endregion
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 执行宏
        /// </summary>
        /// <param name="oApp">Excel对象</param>
        /// <param name="oRunArgs">参数(第一个参数为指定宏名称,后面为指定宏的参数值)</param>
        /// <returns>宏返回值</returns>
        private object RunMacro(object oApp, object[] oRunArgs)
        {
            try
            {
                // 声明一个返回对象
                object objRtn;

                // 反射方式执行宏
                objRtn = oApp.GetType().InvokeMember(
                                                        "Run",
                                                        System.Reflection.BindingFlags.Default |
                                                        System.Reflection.BindingFlags.InvokeMethod,
                                                        null,
                                                        oApp,
                                                        oRunArgs
                                                     );

                // 返回值
                return objRtn;

            }
            catch (Exception ex)
            {
                // 如果有底层异常,抛出底层异常
                if (ex.InnerException.Message.ToString().Length > 0)
                {
                    throw ex.InnerException;
                }
                else
                {
                    throw ex;
                }
            }
        }

        public void saveExcel()
        {
            string filePath = System.Reflection.Assembly.GetExecutingAssembly().Location;
            //string directoryPath = System.IO.Path.GetDirectoryName(filePath);
            //string excelPath = System.IO.Path.Combine(directoryPath, "ExcelFile.xlsx");

            Excel.Application excelApp = new Excel.Application();
            Workbook workbook = excelApp.ActiveWorkbook;
            workbook.SaveAs("C:\\Users\\username\\Documents\\test.xlsm", XlFileFormat.xlOpenXMLWorkbookMacroEnabled);

        }
        //添加宏,执行宏
        public void AddMacro()
        {
            try
            {

                // open excel file 
                const string excelFile = @"C:\Users\Desktop\vba\test1.xlsm";
                var excelApplication = new Excel.Application { Visible = true };
                var targetExcelFile = excelApplication.Workbooks.Open(excelFile);

                // add standart module to file
                var newStandardModule = targetExcelFile.VBProject.VBComponents.Add(vbext_ComponentType.vbext_ct_StdModule);
                var codeModule = newStandardModule.CodeModule;

                // add vba code to module
                var lineNum = codeModule.CountOfLines + 1;
                var macroName = "Button1_Click";
                var codeText = "Public Sub " + macroName + "()" + "\r\n";
                codeText += "  MsgBox \"Hi from Excel\"" + "\r\n";
                codeText += "End Sub";

                codeModule.InsertLines(lineNum, codeText);
                targetExcelFile.Save();

                // run the macro
                var macro = string.Format("{0}!{1}.{2}", targetExcelFile.Name, newStandardModule.Name, macroName);
                excelApplication.Run(macro);

                excelApplication.Quit();

            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
                throw;
            }
        }

        //添加透视表选定宏,执行宏
        public void AddMacroWatcher()
        {
            try
            {

                // open excel file 
                const string excelFile = @"C:\Users\Desktop\vba\test2.xlsm";
                var excelApplication = new Excel.Application { Visible = true };
                var targetExcelFile = excelApplication.Workbooks.Open(excelFile);

                // add standart module to file
                var newStandardModule = targetExcelFile.VBProject.VBComponents.Add(vbext_ComponentType.vbext_ct_StdModule);
                //var newworksheetModule = targetExcelFile.VBProject.VBComponents.Add(vbext_ComponentType.vbext_ct_Document);
                //var newworksheetModule = targetExcelFile.VBProject.VBComponents.Item("Sheet1");
                var codeModule = newStandardModule.CodeModule;
                // var codeModule = newworksheetModule.CodeModule;
                /****
                 * 
                 * Private Sub Worksheet_SelectionChange(ByVal Target As Range)

                    Open "C:\Users\leo_b\Desktop\testvba3.txt" For Output As #1
                    Dim cell As Range
                     Dim str As String
                      For Each cell In Selection
                       str = str & cell.Value & vbNewLine
                      Next cell
                         Print #1, str
                        Close #1
                      MsgBox str + "写入完成"
                    End Sub
                 * 
                 ***/

                // add vba code to module
                var lineNum = codeModule.CountOfLines + 1;
                var macroName = "Worksheet_SelectionChange";
                var codeText = "Private Sub " + macroName + "(ByVal Target As Range)" + "\r\n";
                // codeText += " Open \"C:\\Users\\leo_b\\Desktop\\testvba3.txt\" For Output As #1" + "\r\n";
                codeText += " Open \"" + excelFile + "\" For Output As #1" + "\r\n";
                codeText += "   Dim cell As Range" + "\r\n";
                codeText += "     Dim str As String" + "\r\n";
                codeText += "      For Each cell In Selection" + "\r\n";
                codeText += "    str = str & cell.Value & vbNewLine" + "\r\n";
                codeText += "    Next cell" + "\r\n";
                codeText += "    Print #1, str" + "\r\n";
                codeText += "    Close #1" + "\r\n";
                codeText += "  MsgBox \"写入完成1\"" + "\r\n";
                codeText += "End Sub";

                codeModule.InsertLines(lineNum, codeText);
                targetExcelFile.Save();

                //  excelApplication.SheetSelectionChange += Application_SheetSelectionChange;

                // run the macro
                var macro = string.Format("{0}!{1}.{2}", targetExcelFile.Name, newStandardModule.Name, macroName);
                // var macro = string.Format("{0}!{1}.{2}", targetExcelFile.Name, newworksheetModule.Name, macroName);
                excelApplication.Run(macro);

                excelApplication.Quit();

            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
                throw;
            }
        }
        private void Application_SheetSelectionChange(Object sh, Range Target)
        {
            // Target.Value = DateTime.Today.ToString("yyyy-MM-dd HH:mm:ss");
            // xlRange = (Globals.ThisAddIn.Application.ActiveCell as Excel.Range).CurrentRegion;
            // 在selectchange事件中运行VBA代码
            // ThisWorkbook.Application.Run("VBA代码名称");

        }

        public void vbarun()
        {
            //获取当前工作表
            // Excel.Worksheet worksheet = Globals.ThisAddIn.Application.ActiveSheet;
            //创建Excel Application对象
            Excel.Application excelApp = new Excel.Application(); //隐藏Excel窗口 
            excelApp.Visible = false; //打开Excel文件
            Workbook workbook = excelApp.Workbooks.Open("C:\\Users\\leo_b\\Desktop\\vba\\test3.xlsm");
            //saveExcel();
            string excelFile = "C:\\Users\\leo_b\\Desktop\\testvba3.txt";
            //获取第一个工作表 
            Worksheet worksheet = (Worksheet)workbook.Worksheets[1];
            // 定义VBA代码
            //string vbaCode = "Sub HelloWorld() \n" + "MsgBox "Hello, World!" \n" + "End Sub";
            var macroName = "Worksheet_SelectionChange";
            var vbaCode = "Private Sub " + macroName + "(ByVal Target As Range)" + "\r\n";
            // codeText += " Open \"C:\\Users\\leo_b\\Desktop\\testvba3.txt\" For Output As #1" + "\r\n";
            vbaCode += " Open \"" + excelFile + "\" For Output As #1" + "\r\n";
            vbaCode += "   Dim cell As Range" + "\r\n";
            vbaCode += "     Dim str As String" + "\r\n";
            vbaCode += "      For Each cell In Selection" + "\r\n";
            vbaCode += "    str = str & cell.Value & vbNewLine" + "\r\n";
            vbaCode += "    Next cell" + "\r\n";
            vbaCode += "    Print #1, str" + "\r\n";
            vbaCode += "    Close #1" + "\r\n";
            vbaCode += "  MsgBox \"写入完成1\"" + "\r\n";
            vbaCode += "End Sub";
            // 运行VBA代码
            worksheet.Parent.GetType().InvokeMember("Run", System.Reflection.BindingFlags.Default | System.Reflection.BindingFlags.InvokeMethod, null, worksheet.Parent, new object[] { vbaCode });

        }

        public string Reader(string readfile)
        {
            //string ExcelPath = System.Reflection.Assembly.GetExecutingAssembly().Location;
            //int last = ExcelPath.LastIndexOf("\\");
            //ExcelPath = ExcelPath.Substring(0, last);
            //TODO 20230522 合并透视表的数据和具体字段定义信息
            try
            {
                //data
                string readfiled = "";
                readfiled = readfile + "\\testvba2.txt";
                StreamReader sr = new StreamReader(readfiled, Encoding.UTF8);
                String line;
                string text = "";
                while ((line = sr.ReadLine()) != null)
                {
                    text += line.ToString();
                }
                //toushibiao
                string readfilet = "";
                readfilet = readfile + "\\testvba3.txt";
                StreamReader srp = new StreamReader(readfilet, Encoding.UTF8);
                String linep;
                string textp = "";
                while ((linep = srp.ReadLine()) != null)
                {
                    textp += linep.ToString();
                }

                return text + "," + textp;


            }
            catch (Exception ex)
            {
                return "";
            }
        }

        /// <summary>
        /// 取得语句中的VBA
        /// </summary>
        /// <param name="vba">整个语句</param>
        /// <returns>标准的VBA</returns>
        public string SubstringVBA(string vba)
        {
            int sub = vba.IndexOf("```");//vba语句开始索引
            int endsub = vba.LastIndexOf("```");//vba语句结束索引
            vba = vba.Remove(endsub);//移除vba尾部不相关语句
            sub = vba.IndexOf("```");//重新计算vba开头
            vba = vba.Substring(sub + 3);//从vba开头拿vba语句
            return vba;
        }
        /// <summary>
        /// 执行VBA
        /// </summary>
        /// <param name="filePath">路径</param>
        /// <param name="componentName">模块名称</param>
        /// <param name="procedureName">事件过程名称</param>
        /// <param name="vbaCode">vba代码</param>
        public void ExecuteVbaCode(string filePath, string componentName, string procedureName, string vbaCode)
        {
            //componentName = "模块1";
            //procedureName = "Button1_Click";//事件过程名称
            //vbaCode vba代码
            // vbaCode = "Public Sub " + procedureName + "()" + "\r\n";
            //vbaCode += "  MsgBox \"Hi from Excel of vba\"" + "\r\n";
            //vbaCode += "End Sub";
            //filePath = @"C:\Users\Desktop\vba\test1.xlsm";
            try
            {
                Excel.Application excelApp = new Excel.Application();
                excelApp.Visible = true;  //不显示Excel应用程序

                Excel.Workbook workbook = excelApp.Workbooks.Open(filePath);

                VBIDE.VBE vbe = workbook.VBProject.VBE;
                //新建模块名,不用参数名
                var newStandardModule = workbook.VBProject.VBComponents.Add(vbext_ComponentType.vbext_ct_StdModule);
                componentName = newStandardModule.Name;
                //
                VBIDE.VBComponent vbComponent = vbe.ActiveVBProject.VBComponents.Item(componentName); //此处为代码模块名称

                VBIDE.CodeModule code = vbComponent.CodeModule;
                var lineNum = code.CountOfLines + 1;
                code.InsertLines(lineNum + 1, vbaCode);  //此处为要插入执行的VBA代码

                excelApp.Run(componentName + "." + procedureName);  //执行指定代码模块的过程或函数, 此处为代码模块名称和过程或事件名称

                workbook.Close(false);
                excelApp.Quit();
                System.Runtime.InteropServices.Marshal.ReleaseComObject(workbook);
                System.Runtime.InteropServices.Marshal.ReleaseComObject(excelApp);
            }
            catch (Exception ex)
            {
                //Common.SaveLog("Run VBA Exception:", ex.Message);
            }

        }
        //Sub PrintRangeCoordinateInfo()
        /// <summary>
        /// 取得语句中的ProcedureName
        /// </summary>
        /// <param name="vbaS">整个语句</param>
        /// <returns>标准的VBA</returns>
        public string SubsProcedureName(string vbaS)
        {
            //vbaS = "Sub PrintRangeCoordinateInfo()";
            int sub = vbaS.IndexOf("Sub");//sub语句开始索引
            int endsub = vbaS.IndexOf("()");//ProcedureName语句结束索引
            vbaS = vbaS.Remove(endsub);//移除vba尾部不相关语句
            sub = vbaS.IndexOf("Sub");//重新计算vba开头
            vbaS = vbaS.Substring(sub + 3);//从vba开头拿sub开头语句
            return vbaS;
        }
    }
}

 

标签:vba,string,C#,Excel,VBA,System,var,vbaCode,底层
From: https://www.cnblogs.com/shiningleo007/p/17422597.html

相关文章

  • Unity3D高级编程主程手记 学习笔记二:C#技术要点
    1.Untiy3D中C#的底层原理Unity底层在运行C#程序时有两种机制:一种是Mono,另一种是IL2CPP。Mono存在的目的是为了跨平台,因为最初C#只支持Windows。而IL可以看成是一种汇编语言且完全基于堆栈,必须运行在虚拟机上。也就是说C#会被编译器编译成IL,当需要他们时就会被实时的加载到运行库......
  • 【MySQL】MySQL执行一条 select 语句,期间发生了什么?
    1  前言我们学习SQL的时候,大家肯定第一个先学到的就是select查询语句了,比如下面这句查询语句://在product表中,查询id=1的记录select*fromproductwhereid=1;但是有没有想过,MySQL执行一条select查询语句,在MySQL中期间发生了什么?带着这个问题,我们可以......
  • js 连接数据库 提示:ActiveXObject is not defined
    ActiveXObjectisnotdefined最近比较闲,上班瞎捣鼓一下,没想到报错了,提示ActiveXObjectisnotdefined大概是在js连接数据库时new对象使用的是ActiveXObject完事儿使用的浏览器是edge,但是在ie就没有问题,那么估计就是浏览器的设置问题点开edge的设置然后在默认浏览器的侧栏......
  • Kernel panic 堆栈信息怎么看
    Kernelpanic是指Linux内核遇到了无法继续执行的致命错误,此时会在屏幕上输出一些错误信息,其中就包括堆栈信息。堆栈信息是指发生错误时CPU执行的代码路径,可以通过堆栈信息来定位错误发生的位置。通常,堆栈信息会以类似下面的形式输出:Kernelpanic-notsyncing:Attempted......
  • .net6中数据库查询报错:'OFFSET' 附近有语法错误。 在 FETCH 语句中选项 NEXT 的用法无
    错误语句:在数据库查询中使用skip()问题原因:数据库版本为SQLServer2008,不支持'Fetch'和'Next'语句SQLServer2012及后续版本才支持相关语句解决方法:1.引用包: System.Data.SqlClient和EntityFrameworkCore.UseRowNumberForPaging2.使用:在Program.cs中调整数据库连接bu......
  • Git拉取代码报错:Can't Update No tracked branch configured for branch dev or the b
    错误: 解决方法:第一步:gitpullorigin(远程仓库名称)develop(远程分支名称)--allow-unrelated-histories第二步:gitbranch--set-upstream-toorigin(远程仓库名称)/develop(远程分支名称)dev(本地分支名称)显示如下则为成功,可正常拉取代码 ......
  • 今天,我问了ChatGPT一个难以启齿的问题,内容实录
    文/高扬(微信公众号:量子论) 七个月前,我是一个害怕失业的漂泊上海的小青年,每天在合租房里刷着LeetCode。 现在我已经在一家人工智能公司从事着自己喜欢的关于机器深度学习的研发工作。 你想知道我的生活发生了什么变化吗? 你绝对想不到。 我的生活没有发生任何变......
  • NPOI读取Excel数据
    usingSystem.Data;usingSystem.Data.SqlClient;usingSystem.IO;usingNPOI.HSSF.UserModel;//用于处理Excel的NPOI库html<f:FileUploadID="fileUpload"runat="server"AllowMultiFile="false"/> C#protectedvoidUploadButton_Cl......
  • delphi RTC 解析statucode 问题
    开源的版本也一样会。rtcinfo.pas,以下的解析 StatusCode 有问题,如果服务器返回的是“HTTP/1.1200” 后面没有状态文本。会解析不到 状态码,这里应该按标准格式来,协议 空格 状态码 空格 状态文本一个一个解析才对,但是RTC 认为状态码、文本是要一起有的。例子:同一个请......
  • MAC97A6-ASEMI代理长电原厂双向可控硅MAC97A6
    编辑:llMAC97A6-ASEMI代理长电原厂双向可控硅MAC97A6型号:MAC97A6品牌:长电\CJ封装:TO-92特性:可控硅正向电流:0.6A反向耐压:400V触发电压:0.62~0.8V引脚数量:3芯片个数:1芯片尺寸:浪涌电流:40A特点:单向可控硅工作温度:-40℃~125℃MAC97A6应用范围:通用双向开关,相位控制应用,固态......