質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.44%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Q&A

解決済

2回答

28382閲覧

C# のプログラムから、エクセルマクロを実行したい

hiro25

総合スコア16

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

0グッド

0クリップ

投稿2016/07/22 14:24

困っております。お力を貸してください。

■やりたいこと
C#のプログラムから、すでに開かれているエクセルのマクロを実行したい。

■C#側のプログラムコード

C#

1using System; 2using System.Collections.Generic; 3using System.Linq; 4using System.Text; 5using System.Threading.Tasks; 6using System.Collections; 7using System.Runtime.InteropServices; 8using Microsoft.Office.Interop.Excel; 9 10namespace HogeHoge.cls 11{ 12 class clsExcelCtrl : IDisposable 13 { 14 // Excel操作用オブジェクト 15 private Application xlApp = null; 16 private Workbooks xlBooks = null; 17 private Workbook xlBook = null; 18 private Sheets xlSheets = null; 19 private Worksheet xlSheet = null; 20 private bool isDispose; 21 22 // ------------------------------------------------------ 23 // コンストラクタ/デストラクタ・プロパティ・メソッド 24 // ------------------------------------------------------ 25 /// <summary> 26 /// コンストラクタ 27 /// </summary> 28 public clsExcelCtrl() 29 { 30 xlApp = new Application(); 31 isDispose = false; 32 } 33 34 /// <summary> 35 /// 解放 36 /// </summary> 37 public void Dispose() 38 { 39 // ExcelManagerが使われなくなったときに破棄する資源 40 ReleaseExcelComObject(EnumReleaseMode.App); 41 42 // dispose判定フラグON 43 isDispose = true; 44 45 // Dispose()が明示的に呼ばれたときは、GCからFinalize()呼び出しをさせない。 46 GC.SuppressFinalize(this); 47 } 48 49 /// <summary> 50 /// デストラクタ 51 /// </summary> 52 ~clsExcelCtrl() 53 { 54 // 呼出し側がDispose()してなかったらここでDispose 55 if (isDispose == false) 56 { 57 Dispose(); 58 } 59 } 60 61 /// <summary> 62 /// リリース対象 63 /// </summary> 64 private enum EnumReleaseMode 65 { 66 Sheet, 67 Sheets, 68 Book, 69 Books, 70 App 71 } 72 73 /// <summary> 74 /// Excelリソース解放 75 /// </summary> 76 /// <param name="ReleaseMode">リリース対象Enum</param> 77 private void ReleaseExcelComObject(EnumReleaseMode ReleaseMode) 78 { 79 try 80 { 81 // xlSheet解放 82 if (xlSheet != null) 83 { 84 Marshal.ReleaseComObject(xlSheet); 85 xlSheet = null; 86 } 87 if (ReleaseMode == EnumReleaseMode.Sheet) 88 return; 89 90 // xlSheets解放 91 if (xlSheets != null) 92 { 93 Marshal.ReleaseComObject(xlSheets); 94 xlSheets = null; 95 } 96 if (ReleaseMode == EnumReleaseMode.Sheets) 97 return; 98 99 // xlBook解放 100 if (xlBook != null) 101 { 102 try 103 { 104 //xlBook.Close(); 105 } 106 finally 107 { 108 Marshal.ReleaseComObject(xlBook); 109 xlBook = null; 110 } 111 } 112 if (ReleaseMode == EnumReleaseMode.Book) 113 return; 114 115 // xlBooks解放 116 if (xlBooks != null) 117 { 118 Marshal.ReleaseComObject(xlBooks); 119 xlBooks = null; 120 } 121 if (ReleaseMode == EnumReleaseMode.Books) 122 return; 123 124 // xlApp解放 125 if (xlApp != null) 126 { 127 try 128 { 129 // アラートを戻して終了 130 //xlApp.DisplayAlerts = true; 131 //xlApp.Quit(); 132 } 133 finally 134 { 135 Marshal.ReleaseComObject(xlApp); 136 } 137 } 138 } 139 catch (Exception) 140 { 141 // throw; 142 } 143 } 144 145 146 /// <summary> 147 /// マクロ実行 148 /// </summary> 149 /// <param name="pPara"></param> 150 /// <returns></returns> 151 public bool Run(string pPara) 152 { 153 try 154 { 155 xlApp.Run("iTest", pPara); 156 } 157 catch 158 { 159 return false; 160 } 161 162 return true; 163 } 164 165 /// <summary> 166 /// 開いているExcelを取得 167 /// </summary> 168 /// <returns></returns> 169 public bool GetExcelObject() 170 { 171 // 開いているExcelを取得 172 try 173 { 174 xlApp = (Microsoft.Office.Interop.Excel.Application)Marshal.GetActiveObject("Excel.Application"); 175 } 176 catch (COMException) 177 { 178 //Excelが起動されていません 179 return false; 180 } 181 // 開いているExcelのBookを取得 182 // <MEMO> 183 // Excel操作ソフトを実行中に強制終了などするとCOMオブジェクトの解放モレが発生し、 184 // プロセスが残る状態になる。その状態で再度Excel操作をしようとすると、残った 185 // プロセスの方を操作対象としてしまう。結果、新しいブックを開いていても以下の操作に 186 // 失敗することがある。この場合、タスクマネージャーからEXCEL.EXEプロセスをキルする必要がある。 187 try 188 { 189 xlBooks = xlApp.Workbooks; 190 if (xlBooks.Count == 0) 191 { 192 //プロセスが残っていないか確認してください 193 return false; 194 } 195 xlBook = xlBooks.get_Item(1); 196 } 197 catch (COMException) 198 { 199 return false; 200 } 201 return true; 202 } 203 204 205 } 206} 207

上記のクラスを呼び出す側のプログラム

C#

1if (!objExcelCtrl.GetExcelObject()) //←これは正常に通る 2{ 3 return; 4} 5objExcelCtrl.Run("これはテストです"); //←これがうまく実行されない!

エクセルマクロのプログラム

Excel

1'エクセルマクロ 2Public Function iTest(ByVal pMsg As String) 3 Cells(10, 1) = pMsg 4End Function

この状態で、objExcelCtrl.Run()を実行すると、例外エラーが発生します。
そのメッセージ内容は、

マクロ 'iTest' を実行できません。このブックでマクロが使用できないか、またはすべてのマクロが無効になっている可能性があります。

というメッセージが表示されます。

エクセルのセキュリティーセンターの設定内容は、
「すべてのマクロを有効にする」が設定されている状態です。

何が原因なのか、解決方法を教えてください。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

自己解決

自己解決しました。

エクセルマクロの記述箇所を、シートに書いていたのですが、
それを標準モジュール内に記述したらうまくマクロが動作しました。

ご回答していただきまして、ありがとうございました。

投稿2016/07/22 15:32

hiro25

総合スコア16

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

flied_onion

2016/07/22 16:08

動作したようで良かったです。 Sheetのマクロを実行したい場合は、関数名の前にシートのオブジェクト名(VBAウィンドウのプロパティで確認できます)を付ければうまくいくと思います。 オブジェクト名がSheet1の場合: ```csharp xlApp.Run("Sheet1.iTest", pPara); ```
guest

0

直接の回答ではないですが、Win10 + VS2013(.NET4.5.2) + Excel 2013 の環境で、以下のコードはうまく動作します。

コードはクリックイベントだけですが、新規フォームにボタンを置いてクリックイベントを以下の様に実装しただけのものです。

csharp

1private void button1_Click(object sender, EventArgs e) { 2 dynamic xlApp = Marshal.GetActiveObject("Excel.Application"); 3 dynamic xlBooks = xlApp.Workbooks; 4 dynamic xlBook = xlBooks.Item(1); 5 6 xlApp.Run("iTest", "val"); 7 8 Marshal.FinalReleaseComObject(xlBooks); 9 Marshal.FinalReleaseComObject(xlBook); 10 Marshal.FinalReleaseComObject(xlApp); 11}

Excelを開いたのち、新規ブック(保存もしていない)にマクロを追加して上記のプログラムを実行するだけです。

違いとしてはget_ItemではなくItemを使っているところぐらいです。

マクロ 'iTest' を実行できません。このブックでマクロが使用できないか、またはすべてのマクロが無効になっている可能性があります。

このエラーは、存在しないマクロを指定した場合にも発生します。
取得したExcelが目的のプロセスではない(実はExcelが複数起動していて、違う方のExcelを取得してしまっている)とか、マクロのないBookを取得してしまっていないかも確認してみるといいかもしれません。

余談ですが、GetExcelObjectのxlBooksの処理中の例外処理では、xlAppやxlBooksがnullでなければ解放する(ReleaseComObject)処理を入れた方が良いでしょう。

投稿2016/07/22 15:13

flied_onion

総合スコア2604

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.44%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問