🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
VBA

VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

C#

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

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

マクロ

定義された処理手続きに応じて、どのような一連の処理を行うのかを特定させるルールをマクロと呼びます。

Q&A

解決済

1回答

3771閲覧

C#でExcelマクロボタンのクリックイベントを発生させる方法、VBAのApplication.callerを扱う方法

Daiki_CSharp

総合スコア5

VBA

VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

C#

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

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

マクロ

定義された処理手続きに応じて、どのような一連の処理を行うのかを特定させるルールをマクロと呼びます。

0グッド

0クリップ

投稿2019/11/22 01:57

前提・実現したいこと

C#でコーディングしており、Excelのマクロ(VBA)実行を試みています。
C#でExcelをOpenするところまでは難なく実装できております。
単純にVBAマクロを呼び出すだけであれば .Run メソッドを用いれば可能なのですが、
肝心のマクロ内に Application.caller を使った分岐があり、そもそもC#から呼ばれることを想定していないマクロである為難儀しております。

そもそものExcelには、日付(1~31)が縦に並んでおり、その各日付の横に [+] [-] のボタンが設置されているようなイメージです。(ボタンは計62個(31日 x 2種))

該当のソースコード(抜粋)

呼び出したいVBAマクロと、コーディングしているC#の現況の2部構成で記載いたします。

C#

1 2 // Excel.Application のインスタンス生成 3 Microsoft.Office.Interop.Excel.Application xlApp = null; 4 xlApp = new Microsoft.Office.Interop.Excel.Application(); 5 Microsoft.Office.Interop.Excel.Workbooks xlBooks = null; 6 Microsoft.Office.Interop.Excel.Workbook xlBook = null; 7 Microsoft.Office.Interop.Excel.Sheets xlSheets = null; 8 Microsoft.Office.Interop.Excel.Worksheet xlSheet = null; 9 10 // オープン 11 xlBooks = xlApp.Workbooks; 12 xlBook = xlBooks.Open(@"D:\share\work\Book1.xlsx",0,false); 13 14 xlSheets = xlBook.Worksheets; 15 // 初めのシートを参照 16 xlSheet = xlSheets[1] as Microsoft.Office.Interop.Excel.Worksheet; 17 18 'この辺りまでは動作確認できており、これより後ろの実装(マクロ呼出し方法)に苦戦しています。 19 20 '(困り果てていて未実装です)

VBA

1Public Sub sub_AddDel_DayLine() 2 On Error GoTo ERR_TRAP 3 4 Dim strButtonName As String 'マクロを呼び出したボタン名(BtnAdd01~31 or BtnDel01~31) 5 Dim strShori As String '追加(Add)/削除(Del) 6 7 'ボタン名から処理区分、対象日を取得 8 strButtonName = Application.Caller 9 10 '処理区分(追加/削除) 11 If InStr(strButtonName, "Add") Then 12 strShori = "Add" 13 ElseIf InStr(strButtonName, "Del") Then 14 strShori = "Del" 15 End If 16 17 Select Case strShori 18 Case "Add" 19 '省略(追加処理) 20 21 Case "Del" 22 '省略(削除処理) 23End Sub

Application.caller 部分で押下されたボタン名を取得し、どの日付のどのボタンが押されたかに応じて分岐しているマクロのようです。
諸事情あり、VBA側には変更を加えられないので、C#だけでこのマクロを正しく動かしたいと考えています。

試したこと

VBAを呼び出す前に、C#側で Application.caller に値を代入したらいいのではないか、など考えてみましたが、VBAのプロパティをC#で設定することはできないようで(当たり前?)うまくいきませんでした。

C#で、マクロが設定されているボタン名称を指定してクリックイベントを発生させるのが有力手段かなと考えているのですが、
ボタン名称指定でクリックイベントを起こす方法を調べても見つけられませんでした。

###ご相談内容
・C#でExcelのマクロボタンの名称を指定してクリックイベントを起こす方法
もしくは
・呼び先VBAの Application.caller をC#で扱う(設定する)方法

のいずれかについてご教示いただけませんでしょうか。
よろしくお願い致します。

補足情報(FW/ツールのバージョンなど)

VisualStudio 2019(.NET Framework 4.7.2)

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

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

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

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

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

m.ts10806

2019/11/22 02:05

なぜわざわざC#からExcel操作を?
Daiki_CSharp

2019/11/22 05:36 編集

現在開発に使っているローコード開発プラットフォームがサポート(≒呼出し可能な外部クラス)しているのがC#のみだから、という理由です。 「ローコード」だけでは作りこめない処理を C#(VisualStudio)でコーディングしています。 一方で、エンドユーザにExcelの存在を意識させたくないが、他システムと連携する為にExcelを作成する必要がある、という背景もあります。 旧来、ユーザがExcelを作成・入力し、WebシステムAへアップロードしていましたが、 ユーザのExcel操作をやめたい為、その業務をラップする形でWebシステムB(ローコード)を作っています。 ユーザはシステムBのみを操作するが、システムAはExcelしか受け付けていないので、Bの裏ではExcelを作りAへ連携させなければならない、という事情です。
guest

回答1

0

ベストアンサー

まず正攻法では無理だと思います。

  • ExcelのApplication.Callerは読み取り専用プロパティとして提供されているため通常手段で変更は不可能
  • Excelの図形を示すShapeクラスやフォームコントロールのボタンをButtonクラスにはClickのようなAPIが提供されていない

上記の2点が理由です。

既存のブックのVBAのコードを変更するのが最も手っ取り早い(数行変えれば済む)ですが、それは難しいとのことなので、他の案を考えてみました。

1. ユーザー操作エミュレート

マウス操作をエミュレートして、ボタンをクリックさせます。
試した限りキーボード操作は受け付けなかったので、マウス操作のエミュレートが必須だと思われます。

2. 他のApplication.Callerを参照する機能から呼び出す

Caller プロパティ (Excel) | Microsoft Docs

を見ると、ボタンクリック以外でもApplication.Callerが設定されるパターンがあります。

手元で試したところ、Auto_Openなどの「Auto_*」系では[ブックのファイル名]ブックの先頭シート名の文字列が設定されました。

sub_AddDel_DayLineではInStrで条件を判定しているため、
適当なブックに「Auto_*」のSubプロシージャを作成し、そのプロシージャからsub_AddDel_DayLineを呼び出せば記載されている分の処理は通ると思います。
Auto_*」のSubプロシージャからApplication.Runを実行してもApplication.Callerを取得できることは確認しました。

また

Workbook の RunAutoMacros メソッド (Excel) | Microsoft Docs

を使用すれば、任意の「Auto_*」のSubプロシージャを実行できるため、任意のタイミングの実行も可能です。

投稿2019/11/22 13:41

imihito

総合スコア2166

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

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

imihito

2019/11/22 13:53

中の処理を見れるなら、他のブックなり、VBScriptなりにコピぺして、元のブックの処理を使わずにそちらから処理をさせる手もありますね(C#からやってもいいですが構文の修正とCOM解放処理があるので…)
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問