Erreurs lors de l’appel de certaines macros Excel VBA à partir de C #

Je me débattais et je cherchais vainement ce problème … J’ai quelques macros de test qui fonctionnent parfaitement lorsqu’elles sont exécutées à partir d’Excel, mais échouent ou ne fonctionnent pas lorsqu’elles sont appelées à partir de C #, en utilisant l’interopérabilité …

J’utilise MS Visual Studio 2012 (sous Windows 7 64 bits) pour créer une application console qui appellera la macro VBA TestMacro () écrite dans Excel 2007.

Voici le code C # pour appeler la macro: (j’ai essentiellement copié ce qui a été fait ici Exécuter des macros Office à l’aide de Automation à partir de Visual C # .NET )

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(ssortingng[] 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); } } } 

Les macros sont …

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

Cette macro échoue avec ComException dans Visual Studio -> “Exception de HRESULT: 0x800A03EC”

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

Ne renvoie pas d’exception, mais n’efface pas le contenu de TestRange

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

Mais cela fonctionne, ainsi le nom de la plage peut être reconnu et l’opération de comptage peut être effectuée …

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

Cela fonctionne comme le dernier cas, mais ne parvient pas à passer à la feuille 2 et écrit le résultat dans la feuille 1 …

Comme indiqué précédemment, toutes ces macros fonctionnent parfaitement lorsqu’elles sont exécutées à partir d’Excel, mais échouent lorsqu’elles sont appelées à partir de C #. Aucune des feuilles de travail n’est protégée et j’ai défini les options “Activer toutes les macros”, “Accès sécurisé au modèle de projet VBA” dans Macro Security. Je pense qu’il y a un problème d’access / permissions, mais je n’ai aucune idée de la façon de le résoudre …. toute aide serait appréciée.

Merci d’avance!!

Il pourrait y avoir plusieurs choses qui vous manquent. Voici tout d’abord le code que j’ai utilisé pour le faire fonctionner, à l’aide de la référence .Net Microsoft.Office.Interop.Excel v14 (pour Office 2010):

 using System; using Microsoft.Office.Interop.Excel; namespace ConsoleApplication5 { class Program { static void Main(ssortingng[] 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); } } } 

Deuxièmement, assurez-vous de placer le code de macro dans un module (un fichier BAS global).

 Public Sub TestMsg() MsgBox ("Hello Stackoverflow") End Sub 

Troisièmement, assurez-vous d’activer l’access Macro Security and Trust au modèle d’object de projet VBA:

entrez la description de l'image ici

En outre, est-ce que quelqu’un sait s’il existe un moyen de déboguer Excel VBA à partir de Visual Studio 2012, les exceptions Com ne sont pas très utiles … – Sunny Sampath

Lorsque vous surmontez l’exception Com, parcourir le code croise les processus de VS dans le VBE d’Excel, puis revient à VS.

Modifier:

Voici le code VBA pour effacer le contenu:

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

Ou si vous souhaitez supprimer un NameRange appelé TestRange:

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

Les autres TestMacro sont trop spécifiques à votre travail pour que je puisse les comprendre. Bonne chance!

Bien apparemment, il y avait une solution très facile. Au lieu d’utiliser la fonction RunMacro … en utilisant la méthode d’application “Run” fonctionne pour toutes les macros. J’ai utilisé la ligne

 oExcel.Run("TestMacro"); 

au lieu d’appeler

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

avec

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

Arghh..Ce numéro a volé 2 jours de ma vie!