简体   繁体   English

从C#调用某些Excel VBA宏时出错

[英]Errors when calling certain Excel VBA macros from C#

I have been struggling and searching on this problem to no avail... I have a few test macros that work perfectly when run from Excel, but either fail or don't work when called from C#, using the interop... 我一直在努力和搜索这个问题无济于事...我有一些测试宏在从Excel运行时工作得很好,但是当从C#调用时,使用interop时失败或不工作...

I am using MS Visual Studio 2012 (on 64 bit Windows 7) to create a console application that will call the VBA macro TestMacro() written in Excel 2007. 我正在使用MS Visual Studio 2012(在64位Windows 7上)创建一个控制台应用程序,该应用程序将调用Excel 2007中编写的VBA宏TestMacro()。

Here is the C# code to call the macro: (I basically copied what was done here Run Office Macros by Using Automation from Visual C# .NET ) 下面是调用宏的C#代码:(我基本上复制了在这里完成的操作从Visual C#.NET使用自动化运行Office宏

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Configuration;
using System.Reflection;
using Excel = Microsoft.Office.Interop.Excel;
using Microsoft.Office.Core;

namespace C#_Macro_Wrapper
{
    class Program
    {
        static void Main(string[] args)
        {
            RunVBATest();
        }


        public static void RunVBATest()
        {
            System.Globalization.CultureInfo oldCI = System.Threading.Thread.CurrentThread.CurrentCulture;
            System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo("en-US");
            object oMissing = System.Reflection.Missing.Value;
            Excel.Application oExcel = new Excel.Application();
            oExcel.Visible = true;
            Excel.Workbooks oBooks = oExcel.Workbooks;
            Excel._Workbook oBook = null;
            oBook = oBooks.Open("C:\\Users\\ssampath\\Documents\\RMS Projects\\Beta 3 Testing\\TestMacroForVSTO.xlsm", oMissing, oMissing,
                oMissing, oMissing, oMissing, oMissing, oMissing, oMissing,
                oMissing, oMissing, oMissing, oMissing, oMissing, oMissing);

            // Run the macro.
            RunMacro(oExcel, new Object[] { "TestMacro()" });


            // Quit Excel and clean up.
            oBook.Close(true, 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;
            System.Threading.Thread.CurrentThread.CurrentCulture = oldCI;
        }


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

The Macros are... 宏是......

Sub TestMacro()  
Worksheets("Sheet1").ClearContents
End Sub

This macro fails with ComException to Visual Studio -> "Exception from HRESULT: 0x800A03EC" 此宏失败,并且ComException为Visual Studio - >“来自HRESULT的异常:0x800A03EC”

Sub TestMacro()
Range("TestRange").ClearContents
End Sub

Does not return exception, but does not clear contents of TestRange 不返回异常,但不清除TestRange的内容

Sub TestMacro()
x = Range("TestRange").Count()
Cells(5, 5).Value = x
End Sub

But this works, thus the range name can be recognized, and the count operation can be done... 但这是有效的,因此可以识别范围名称,并且可以完成计数操作......

Sub TestMacro()
Worksheets("Sheet1").Select
x = Range("TestRange").Count()
Worksheets("Sheet2").Select
Cells(5, 5).Value = x
End Sub

This works like last case, but fails to switch to sheet 2, and instead writes result to sheet 1... 这与前一种情况一样,但无法切换到表2,而是将结果写入表1 ...

As said earlier all these macros work perfectly when run from excel, but fail when called from C#. 如前所述,所有这些宏在从excel运行时都能正常工作,但在从C#调用时会失败。 None of the works sheets are protected, and I have set "enable all macros", "trust access to VBA project model" in Macro Security. 没有任何工作表受到保护,我在宏安全性中设置了“启用所有宏”,“信任访问VBA项目模型”。 I feel there is some access/permissions issue, but I have no idea how to fix it....any help would appreciated.. 我觉得有一些访问/权限问题,但我不知道如何解决它....任何帮助将不胜感激..

Thanks in advance!! 提前致谢!!

There could be several things your missing. 你可能会遗漏几件事。 First here is the code I used to get it working, using the .Net reference Microsoft.Office.Interop.Excel v14 (for Office 2010): 首先是使用.Net参考Microsoft.Office.Interop.Excel v14(对于Office 2010)使用的代码:

using System;
using Microsoft.Office.Interop.Excel;

namespace ConsoleApplication5
{
class Program
{
static void Main(string[] args)
{
    RunVBATest();
}

public static void RunVBATest()
{
    //System.Globalization.CultureInfo oldCI = System.Threading.Thread.CurrentThread.CurrentCulture;
    //System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo("en-US");
    //object oMissing = System.Reflection.Missing.Value;
    Application oExcel = new Application();
    oExcel.Visible = true;
    Workbooks oBooks = oExcel.Workbooks;
    _Workbook oBook = null;
    oBook = oBooks.Open("C:\\temp\\Book1.xlsm");

    // Run the macro.
    RunMacro(oExcel, new Object[] { "TestMsg" });

    // Quit Excel and clean up.
    oBook.Saved = true;
    oBook.Close(false);
    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;
    //System.Threading.Thread.CurrentThread.CurrentCulture = oldCI;
}

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

Second make sure you put the Macro code in a Module (a Global BAS file).. 第二,确保将宏代码放在模块(全局BAS文件)中。

Public Sub TestMsg()

MsgBox ("Hello Stackoverflow")

End Sub

Third make sure you enable Macro Security and Trust access to the VBA Project object model: 第三,确保启用对VBA Project对象模型的宏安全性和信任访问:

在此输入图像描述

Also does anyone know if for this case there is a way to debug Excel VBA from Visual Studio 2012, the Com Exceptions are pretty unhelpful... – Sunny Sampath 也有人知道,对于这种情况,有一种方法从Visual Studio 2012调试Excel VBA,Com Exceptions是非常无益的... - Sunny Sampath

When you overcome the Com exception, stepping through the code will cross processes from VS into Excel's VBE and then back to VS. 当您克服Com异常时,单步执行代码会将VS中的进程跨越到Excel的VBE中,然后再返回VS.

Edit: 编辑:

Here is the VBA code to clear contents: 以下是清除内容的VBA代码:

Dim activeSheet As Worksheet
Set activeSheet = Excel.activeSheet
activeSheet.UsedRange.Clear

Or if you want to delete a NameRange called TestRange: 或者,如果要删除名为TestRange的NameRange:

Dim range As range
Set range = activeSheet.range("TestRange")
range.Clear

The other TestMacro's are too specific to your work for me to understand. 其他TestMacro对你的工作来说太具体了,我无法理解。 Good luck! 祝好运!

Well apparently there was a very easy solution. 显然,有一个非常简单的解决方案。 Instead of using RunMacro function...using the application method "Run" works for all macros. 而不是使用RunMacro函数...使用应用程序方法“运行”适用于所有宏。 I used the line 我用了这条线

oExcel.Run("TestMacro"); 

instead of calling 而不是打电话

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

with

RunMacro(oExcel, new Object[] { "TestMsg" });

Arghh..this issue stole 2 days of my life! 唉......这个问题偷走了我生命的两天!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM