C# と VB.NET の質問掲示板

わんくま同盟

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

ツリー一括表示

C#からExcelマクロの実行 /はるかぜ (18/06/29(Fri) 15:08) #87777
Re[1]: C#からExcelマクロの実行 /魔界の仮面弁士 (18/06/29(Fri) 15:49) #87782 解決済み
│└ Re[2]: C#からExcelマクロの実行 /はるかぜ (18/06/29(Fri) 17:13) #87784 解決済み
Re[1]: C#からExcelマクロの実行 /はるかぜ (18/06/29(Fri) 15:30) #87779 解決済み
  └ Re[2]: C#からExcelマクロの実行 /PANG2 (18/06/29(Fri) 15:33) #87780 解決済み


親記事 / ▼[ 87782 ] ▼[ 87779 ]
■87777 / 親階層)  C#からExcelマクロの実行
□投稿者/ はるかぜ (1回)-(2018/06/29(Fri) 15:08:33)

分類:[C#] 

Microsoft.Office.Interop.Excelを使用してC#からExcelのFunctionを呼んでその戻り値を取得したいと思っています。

VBAは以下のものを「標準モジュール」の場所に作り、Excel上で実行した時は正常に動作することを確認しています。
(JsonConverterも標準モジュールにインポートしてあります)

Public Function ToDotNet() As String
    Dim json As Object
    Set json = CreateObject("Scripting.Dictionary")
    Dim sheet As Worksheet
    Dim arinashi As Boolean
    
    If Sheets(1).rbtnAri.Value Then
        arinashi = True
    Else
        arinashi = False
    End If
    
    json.Add "AriNashi", arinashi
    json.Add "Check1", Sheets(1).chk1.Value
    json.Add "Check2", Sheets(1).chk2.Value
    json.Add "Check3", Sheets(1).chk3.Value

    ToDotNet = JsonConverter.ConvertToJson(json)

End Function

これをC#から実行してjsonを受け取るために以下のコードを書きました。

            Microsoft.Office.Interop.Excel.Application app = null;
            try
            {
                app = new Microsoft.Office.Interop.Excel.Application();
                app.Visible = true;
                var fi = new FileInfo("Template\\template.xlsm");
                var book = app.Workbooks.Open(fi.FullName);
                var ret = app.Run("ToDotNet");
                book.Close();
                Marshal.ReleaseComObject(book);
                richTextBox1.Text = ret;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "エラー", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            finally
            {
                if (app != null)
                {
                    app.Quit();
                }
                app = null;
            }

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

Excelのセキュリティ設定(マクロとActiveXコントロール)をすべて有効(セキュリティなし)にしてみたり、
app.Run("ToDotNet");
の引数を
"'ブック名'!ToDotNet
にしたり、
"'Excelファイルのフルパス'!ToDotNet"
にしたりしてみましたがすべて同じでした。

どうすれば実行できますか?

[ □ Tree ] 返信 編集キー/

▲[ 87777 ] / ▼[ 87784 ]
■87782 / 1階層)  Re[1]: C#からExcelマクロの実行
□投稿者/ 魔界の仮面弁士 (1726回)-(2018/06/29(Fri) 15:49:47)
2018/06/29(Fri) 16:15:11 編集(投稿者)
2018/06/29(Fri) 15:50:16 編集(投稿者)

No87777 (はるかぜ さん) に返信
> var book = app.Workbooks.Open(fi.FullName);
ではなく、
 books = app.Workbooks;
 book = books.Open(fi.FullName);
にします。


> Marshal.ReleaseComObject(book);
book の解放に加えて、books の解放も必要です。
 if( Marshal.IsComObject( books ) ) { Marshal.ReleaseComObject(books); }

変数 app も同様に ReleaseComObject しましょう、Quit 後に。



一方 VBA 側は、下記を直した方が良いでしょう。

> If Sheets(1).rbtnAri.Value Then
Sheets(1) というのが、どのワークブックのシートなのか示されていません。

ThisWorkbook ≠ ActiveWorkbook な可能性もあるわけですから、
「Sheets(1)」ではなく、「対象のワークブックを表す変数.Worksheets(1)」などに
置き換えておくのが望ましいです。



> すべてのマクロが無効になっている可能性があります。
たとえば
 Public Function ToDotNet() As String
  ToDotNet = "{""" & Format(Now, "yyyy/MM/dd HH:mm:ss") & """}"
 End Function
のような、単純な VBA だった場合も、呼び出しに失敗しますか?

単純なものであれば呼び出せるようであれば、VBA コードのどの部分が
問題になっているのかを調べてみては如何でしょう。


# 出遅れすぎた。
## しかも解決済み付け忘れてた。
解決済み
[ 親 87777 / □ Tree ] 返信 編集キー/

▲[ 87782 ] / 返信無し
■87784 / 2階層)  Re[2]: C#からExcelマクロの実行
□投稿者/ はるかぜ (3回)-(2018/06/29(Fri) 17:13:53)
お二方とも回答ありがとうございます。

No87782 (魔界の仮面弁士 さん) に返信
>>Marshal.ReleaseComObject(book);
> book の解放に加えて、books の解放も必要です。
>  if( Marshal.IsComObject( books ) ) { Marshal.ReleaseComObject(books); }
>
> 変数 app も同様に ReleaseComObject しましょう、Quit 後に。
>
>>If Sheets(1).rbtnAri.Value Then
> Sheets(1) というのが、どのワークブックのシートなのか示されていません。
>
> ThisWorkbook ≠ ActiveWorkbook な可能性もあるわけですから、
> 「Sheets(1)」ではなく、「対象のワークブックを表す変数.Worksheets(1)」などに
> 置き換えておくのが望ましいです。
>

ComObjectを使用したExcelの操作自体は経験がありこのようなことも承知していましたが今回はC#とExcel間でJsonのやり取りができるのか確認したかっただけなのでそのへんは適当でした(笑
とりあえずこのエラーが言葉通りの意味でなく、呼び出すマクロが見つからない時やマクロ自体に問題がある時にもでるということがわかったので今後はそういった視点でもチェックするようにします。
解決済み
[ 親 87777 / □ Tree ] 返信 編集キー/

▲[ 87777 ] / ▼[ 87780 ]
■87779 / 1階層)  Re[1]: C#からExcelマクロの実行
□投稿者/ はるかぜ (2回)-(2018/06/29(Fri) 15:30:08)
新規にファイルを作り直して単純にtestという文字列だけ返すFunctionのみを作成したらうまく行ったので
それをもとにJsonConvertを組み込んでVBAも書き換えていったらC#でJsonを取得することができるようになりました。

出来上がったファイルを見比べてみても何が違うのか全くわからないのですが動いたので解決にしておきます。
解決済み
[ 親 87777 / □ Tree ] 返信 編集キー/

▲[ 87779 ] / 返信無し
■87780 / 2階層)  Re[2]: C#からExcelマクロの実行
□投稿者/ PANG2 (215回)-(2018/06/29(Fri) 15:33:12)
2018/06/29(Fri) 15:33:55 編集(投稿者)

まずは、Hello World から

Public Function ToDotNet() As String
ToDotNet = "Hello World"
End Function

# 出遅れた

解決済み
[ 親 87777 / □ Tree ] 返信 編集キー/


管理者用

- Child Tree -