【问题标题】:Running an Excel Macro via C#: Run a macro from one workbook on another?通过 C# 运行 Excel 宏:在另一个工作簿上运行宏?
【发布时间】:2012-12-24 06:57:07
【问题描述】:

我希望运行一个宏,我们在 WorkSheet02 上的 WorkSheet01 中将其称为 Macro01。

使用 Microsoft.Office.Interop.Excel 命名空间我打开了一个 WorkSheet01。

public void Main_CodedStep()
    {
        // Object for missing (or optional) arguments.
        object oMissing = System.Reflection.Missing.Value;

        // Create an instance of Microsoft Excel
        Excel.ApplicationClass oExcel = new Excel.ApplicationClass();

        // Make it visible
        oExcel.Visible = true;

        // Open Worksheet01.xlsm
        Excel.Workbooks oBooks = oExcel.Workbooks;
        Excel._Workbook oBook = null;
        oBook = oBooks.Open("C:\\Users\\Admin\\Documents\\Worksheet01.xlsm", oMissing, oMissing,
            oMissing, oMissing, oMissing, oMissing, oMissing, oMissing, 
            oMissing, oMissing, oMissing, oMissing, oMissing, oMissing);
    }

然后我使用自动脚本来提取报告。此报告是通过 IE 的下载提示而不是 Interop 打开的。

当我尝试通过 C# 运行宏时出现问题(我创建了另一个新的 Excel.ApplicationClass();只是这样编译,我相信这是我的失误之一。)

public void FirstMacro_CodedStep()
    {
        // Create an instance of Microsoft Excel
        Excel.ApplicationClass oExcel = new Excel.ApplicationClass();
        Console.WriteLine("ApplicationClass: " + oExcel);

        // Run the macro, "First_Macro"
        RunMacro(oExcel, new Object[]{"Worksheet01.xlsm!First_Macro"});

        //Garbage collection
        GC.Collect();
    }

    private void RunMacro(object oApp, object[] oRunArgs)
    {
        oApp.GetType().InvokeMember("Run", System.Reflection.BindingFlags.Default | System.Reflection.BindingFlags.InvokeMethod, null, oApp, oRunArgs);
    }

当此方法运行时,它会在 Worksheet01 而不是 Worksheet02 上运行来自 Worksheet01 的宏。它还在“我的文档”中寻找工作表,所以我把它移过来看看会发生什么。

回顾:

  1. 打开 Worksheet01
  2. 通过脚本从 MSIE 获取并打开报告 (Worksheet02)
  3. 在 Worksheet02 上从 Worksheet01 运行 Macro01

资源:

http://support.microsoft.com/kb/306683

http://msdn.microsoft.com/en-us/library/microsoft.office.interop.excel.aspx

对于那些想尝试它的人,请将其添加到您的 using 指令中:

using System.Reflection;
using Microsoft.Office.Core; //Added to Project Settings' References from C:\Program Files (x86)\Microsoft Visual Studio 10.0\Visual Studio Tools for Office\PIA\Office14 - "office"
using Excel = Microsoft.Office.Interop.Excel; //Added to Project Settings' References from C:\Program Files (x86)\Microsoft Visual Studio 10.0\Visual Studio Tools for Office\PIA\Office14 - "Microsoft.Office.Interop.Excel"

【问题讨论】:

    标签: c# excel vba office-automation


    【解决方案1】:

    我找到了一个我想分享的解决方案。 首先,我删除了打开 Worksheet01 的位。然后我让我的自动化脚本将 .CSV 保存到我的文档中。然后我使用我必须打开 Worksheet01 的代码来打开下载的文件。此时的关键是 Worksheet01 与 Worksheet02 位于 Documents 文件夹中。最后,我使用代码从 Worksheet01 运行宏,该宏在 Worksheet02 上运行。

        public void WebTest_CodedStep()
        {
            // Object for missing (or optional) arguments.
            object oMissing = System.Reflection.Missing.Value;
    
            // Create an instance of Microsoft Excel
            Excel.ApplicationClass oExcel = new Excel.ApplicationClass();
    
            // Make it visible
            oExcel.Visible = true;
    
            // Define Workbooks
            Excel.Workbooks oBooks = oExcel.Workbooks;
            Excel._Workbook oBook = null;
    
            // Get the file path
            string path = System.Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
            path = path + "\\Worksheet02.csv";
    
            //Open the file, using the 'path' variable
            oBook = oBooks.Open(path, oMissing, oMissing, oMissing, oMissing, oMissing, oMissing, oMissing, oMissing,  oMissing, oMissing, oMissing, oMissing, oMissing, oMissing);
    
            // Run the macro, "First_Macro"
            RunMacro(oExcel, new Object[]{"Worksheet01.xlsm!First_Macro"});
    
            // Quit Excel and clean up.
            oBook.Close(false, oMissing, oMissing);
            System.Runtime.InteropServices.Marshal.ReleaseComObject (oBook);
            oBook = null;
            System.Runtime.InteropServices.Marshal.ReleaseComObject (oBooks);
            oBooks = null;
            oExcel.Quit();
            System.Runtime.InteropServices.Marshal.ReleaseComObject (oExcel);
            oExcel = null;
    
            //Garbage collection
            GC.Collect();
        }
    
        private void RunMacro(object oApp, object[] oRunArgs)
        {
            oApp.GetType().InvokeMember("Run", System.Reflection.BindingFlags.Default | System.Reflection.BindingFlags.InvokeMethod, null, oApp, oRunArgs);
        }
    

    【讨论】:

    • RunMacro 似乎仅在宏文件位于用户的 Documents 文件夹中时才有效。任何尝试在其他地方提供文件的完整路径都会导致错误消息“未找到宏或宏已被停用”。
    • 是的,我已经进行了几次尝试,这种调用宏的方式(使用 InvokeMember)仅在我的宏在“我的文档”文件夹中的物理上有效。尝试指定其他位置(在该位置复制宏)不起作用。我也尝试过使用 Microsoft.Office.Interop.Excel.Application 类的 Run 方法,它只在相同的条件下工作:“我的文档”文件夹中的宏文件。
    • 代码行:Excel.ApplicationClass oExcel = new Excel.ApplicationClass();在我的 Visual Sudio 中显示错误。相反,我使用的是:使用 Microsoft.Office.Interop.Excel;使用 _Excel = Microsoft.Office.Interop.Excel;然后 _Application excel = new _Excel.Application();我更详细的解决方案在stackoverflow.com/questions/55261892/…
    【解决方案2】:

    我运行这个 C# VSTO 代码来调用 VBA 宏,这是我使用的语法:

    this.Application.Run("mymacro");
    

    编辑:

    宏是工作簿范围内的,也许您需要在运行宏之前将 Sheet2 设为活动工作表,例如:

    foreach (Worksheet worksheet in workbook.Sheets.ComLinq<Worksheet>())
    {
        if (worksheet.Name == "Sheet2") worksheet.Activate();
    }
    

    【讨论】:

    • 抱歉,我没有意识到我的命名约定有点误导。我称之为 Worksheet01 和 Worksheet02 的是两个不同的文件(一个是 xlsm,另一个是 csv)。
    【解决方案3】:
        public void ExecuteMacro()
        {
        //    using Excel = Microsoft.Office.Interop.Excel;
        //    using System;
        //    using System.IO;
    
            string path = Environment.CurrentDirectory;
            string filePath = "";
            string[] fileEntries = Directory.GetFiles(".\\Source");
            foreach (string fileName in fileEntries)
            {
                if (fileName.IndexOf(".xlsm") > 0 && fileName.IndexOf("$")<1) filePath = fileName;
            }
    
            if (filePath == "") return;
    
            filePath = filePath.Replace(".\\", "\\");
            string fileDest = filePath.Replace("Source","Processed");
            filePath = path+filePath;
            fileDest = path+fileDest;
    
            Excel.Application ExcelApp = new Excel.Application();
            Excel.Workbook wb = ExcelApp.Workbooks.Open(filePath, ReadOnly: false);
    
            try
            {
                ExcelApp.Visible = false;
                ExcelApp.Run("UpdateSheets");
    
                try
                {
                    File.Delete(fileDest);
                }
                catch (Exception) { }
    
                wb.SaveAs(fileDest);
            }
            catch (Exception) { }
    
            wb.Close(false);
            ExcelApp.Application.Quit();
            ExcelApp.Quit();
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-18
      • 2015-10-20
      相关资源
      最近更新 更多