4

私は苦労し、この問題を無駄に検索してきました... Excelから実行すると完全に機能するテストマクロがいくつかありますが、相互運用機能を使用してC#から呼び出すと失敗するか機能しません...

MS Visual Studio 2012 (64 ビット Windows 7) を使用して、Excel 2007 で記述された VBA マクロ TestMacro() を呼び出すコンソール アプリケーションを作成しています。

マクロを呼び出す C# コードは次のとおりです。

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);
        }
    }
}

マクロは...

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

このマクロは、Visual Studio への ComException -> "Exception from HRESULT: 0x800A03EC" で失敗します。

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

例外を返さないが、TestRange の内容をクリアしない

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

しかし、これは機能するため、範囲名を認識でき、カウント操作を実行できます...

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

これは最後のケースのように機能しますが、シート 2 への切り替えに失敗し、代わりに結果をシート 1 に書き込みます...

前述のように、これらのマクロはすべて、Excel から実行すると完全に機能しますが、C# から呼び出すと失敗します。どのワークシートも保護されておらず、マクロ セキュリティで「すべてのマクロを有効にする」、「VBA プロジェクト モデルへのアクセスを信頼する」を設定しました。アクセス/許可の問題があると感じていますが、それを修正する方法がわかりません....助けていただければ幸いです..

前もって感謝します!!

4

2 に答える 2

3

どうやら非常に簡単な解決策がありました。RunMacro 関数を使用する代わりに...アプリケーション メソッド「Run」を使用すると、すべてのマクロで機能します。ラインを使った

oExcel.Run("TestMacro"); 

電話する代わりに

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

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

うーん..この問題は私の人生の 2 日を盗んだ!

于 2013-07-01T20:26:01.130 に答える