• ベストアンサー

Excel VBA サブルーチン関連

複数のマクロが標準モジュールに書かれているとします。(例:Module1~Module10) このモジュールを順番に実行するマクロを作成したいのですが、モジュールの名前を指定してサブルーチンコールは出来ないようです。 全部のモジュールを数珠つなぎにして1つのモジュールにまとめる方法は気が進みません。 モジュールの名前を指定してサブルーチンコールするようなスマートな方法はないでしょうか?

質問者が選んだベストアンサー

  • ベストアンサー
回答No.4

#3の回答者です。 各々のシート・オブジェクトに対するものは、ActiveX コントーロールのコマンドボタンを使うというのが通例です。標準モジュールをそのお使いのボタンは、フォームコントロールのボタンをお使いのようです。 フォームボタンの場合は、少し違った使い方をします。フォームボタンは、マクロを兼用で使えるという利点があります。ActiveX コントロールの場合は、同じように出来ますが、かなり難しいコードになってしまいます。 例えばこのようにします。 シート1 に、「ボタン 1」 シート2 に、「ボタン 2」 このボタンには、両方とも、Test1 というマクロを登録しておきます。 以下は簡単な例ですが、このようにして、押したボタンの違いを分けることが可能です。 '標準モジュール Sub Test1()   Select Case Application.Caller() '←Caller を利用する。    Case "ボタン 1": MsgBox "シート1 からです"    Case "ボタン 2": MsgBox "シート2 からです"   End Select End Sub もちろん、Sub ボタン1_Click ()となっているのは、単なるプロシージャですから、 連続して実行するなら、以下のように、並べるだけで結構です。それぞれのモジュールに入っていても、名前が同じでなければ、そのままプロシージャ名だけを書けばよいです。Callを使うのは、特に、引数(パラメータ)がある時に、間違いないように使うためです。できれば、そう習慣づけたほうが間違いが少ないです。 Sub Main()  ボタン1_Click '← 一意(同じものがない)の名前にする  ボタン2_Click End Sub >自分としては Module n の名前を見て Sheet n で使用しているマクロがここに書いてあるくらいの感覚で分かり易いのですが。 やはり、標準モジュールは、そのようにして増やさないほうがよいかと思います。一般の方に、強制する理由などはないのですが、シートモジュールがあるのに、そのような使い方はしないのです。 それから、これは、VBAを扱う人ならほとんどの人は知っていることですが、Application.Run は、他のブックのマクロを実行する時に使います。 「他ブックのマクロを実行する」 http://officetanaka.net/excel/vba/tips/tips09.htm マクロの詳しくない方には、ちょっと難しいかもしれませんが、Application.Run と Call ステートメントでは、以下のように、参照渡しを期待しても、それが出来ないことがあります。だから、ミスをなくすために、Call を使うのです。 '// Sub Test1()  Dim a As Long  a = 10  Application.Run "Macro1", a  MsgBox a '値渡しになってしまいました。 End Sub Sub Test2()  Dim a As Long  a = 10  Call Macro1(a)  MsgBox a End Sub Sub Macro1(ByRef arg As Long) '参照渡し(明示的にByRefを入れました)  arg = 10 * 10 End Sub '// 今回のように単独で使う分には、特に問題は発生しませんが、なるべくコンパクトに分かりやすいように書くのが良いかと思います。

hirombo
質問者

お礼

詳しく説明していただき感謝します。 回答を読みながら、まだVBAが理解出来てないなと感じています。 覚えなくてはならない項目も沢山ありますが、先ずは説明していただいたような基本的な所を勉強しようと思います。 すでに定年を過ぎたシニアの趣味なのでぼちぼちやります。

その他の回答 (3)

回答No.3

こんにちは。 最初に、標準モジュールに書かれているマクロなら、どこに置いてもよいのですが、 ある程度のレベルの人たちは、モジュールは、その作業内容によって分けます。それは、修正しやすいさからです。だから、Module10 とか、10個もモジュールになるということは、まずありえません。管理しにくくなります。あまりモジュールを増やすことはやめたほうがよいです。せいぜい、5個ぐらいです。これ全部で、数千行から、何万行というコードを入れていることもあります。 >全部のモジュールを数珠つなぎにして1つのモジュールにまとめる方法は気が進みません。 それはどちらでもよいのですが、サブルーチンなら、同じモジュールに書きますが、サブプローシージャなら、別々のモジュールに置くことあります。時々、モジュールに1つのプロシージャしか入れていない人がいますが、これはあまり良くない使い方です。 サブルーチンは、もともと、ひとつの流れの中で、編集しやすいように抜き出したコードのことですから、同じモジュールにないとややこしくてしょうがありません。サブプロシージャは、別のモジュールに置くことも多いです。 http://kabu-macro.com/vba_kiso/vba_subprocedure.html #2さんのおっしゃるとおり、 >マクロ(サブルーチン)を実行するマクロの記述は、 >マクロ名を記述するだけでOKです。 サブルーチンなら、マクロ名しか書かないのが一般的です。 しかし、この質問は、コードがどのようなものか分かりませんが、おそらくは、以下のような書き方をします。通常は、同じプロジェクト内では、プロシージャ名は一意の名前を入れるというのがルールですが、この場合は、同名でも、プロシージャが違えば特定できます。(もちろん、この場合は、サブルーチンとは呼びませんし、サブルーチンが別のモジュールにあるというのは不自然です。) 一意の名前ですと、そのままプロシージャ名を書いて平気ですが、そうでない場合は、Mudule名から入れます。ちょうど、メソッドと同じ扱いになります。 Call を入れるのは、サブプロシージャのパラメータの括弧の有無で、参照渡しか、値渡しか混乱することがあるので、Call して、サブプロシージャの本来持っている仕様によって、間違いないようにするためです。 'Module1 Sub Main()  Dim a As Long  a = 20  Call Module2.Macro1(a)  Call Module3.Macro1(a) 'Call抜きと比較してみてください。  MsgBox a 'そのままなら、40と出るはずです。 End Sub 'Module2 Sub Macro1(a As Long)   a = a * 10 End Sub 'Module3 Sub Macro1(a As Long)   a = a / 5 End Sub

hirombo
質問者

補足

回答No.1のお礼欄に今回の質問に至ったいきさつを書いておりますのでご覧いただければ幸いです。 >モジュールは、その作業内容によって分けます。それは、修正しやすいさからです。だから、Module10 とか、10個もモジュールになるということは、まずありえません。 この件についてもう少し教えてください。 当初は1~2枚のシートでスタートしたものが、段々欲が出て(仕様が膨らんで)徐々にシートの枚数が増えてしまうことはよくあることだと思います。 (1枚のシート上に多数のテーブルやグラフを配置すると画面スクロールが頻繁になるので、なるべく別シートを使用するような EXCEL の使い方をしています。) 例えばシート3までは問題なく使えるとして、新たにシート4を作成してこのシートで動作するマクロを作成するとき従来のモジュールに追記する形ではなく、標準モジュールを追加してここにマクロを書く方法を取ってきたためにシート枚数と同数以上の標準モジュールが出来てしまいました。 自分としては Module n の名前を見て Sheet n で使用しているマクロがここに書いてあるくらいの感覚で分かり易いのですが。 強いて言うなら、ほぼ同じ処理を行っている Sub プロシージャが各モジュールの中に重複して書かれているので無駄にプログラムが長くなっていることはあると思います。 ご意見をお聞かせください。

回答No.2

マクロ(サブルーチン)を実行するマクロの記述は、 マクロ名を記述するだけでOKです。 マクロ名に漢字等の文字を使用してもOK。 モジュール名を指定する必要はありません。 Sheets(1).Select マクロ名 Sheets(2).Select メインのデータ(A,B)をサブルーチンに送りたいときは、 マクロ名 A,B 但し、サブルーチン側のマクロ名の後の()の中にA,Bをもらい受ける記述が必要 マクロ名(A,B) また、そのマクロ内で、A,BをDimしないことも必要。

hirombo
質問者

お礼

回答ありがとうございました。

  • keithin
  • ベストアンサー率66% (5278/7940)
回答No.1

こんばんは。 >複数のマクロが標準モジュールに書かれているとします。 1枚のModule1の上に、MAINとMacro1から5までの「プロシジャ」があるとします。 sub main()  dim i  for i = 1 to 5   application.run "Macro" & i  next i end sub それとも? >モジュールの名前を指定してサブルーチンコール 誤記じゃないならModule1から5にいずれもMacro1があるとします。 sub main2()  dim i  for i = 1 to 5  application.run "Module" & i & ".Macro1"  next i end sub

hirombo
質問者

お礼

すばやい回答ありがとうございます。 当方はEXCELもVBAも本格的に使った経験がありません。 30年以上前にアセンブラーを使用した簡単なプログラミング経験、その後に機械制御用PLCのプログラミング経験はあります。 以前よりEXCELというソフトは本当にすごいなと思っており、最近EXCELおよびVBAの勉強を始めたところです。 前置きが長くなりましたが、今回の質問に至ったいきさつについて説明します。 同一のブックに数枚のシートがあり、シート毎に作成した別々のマクロをmodule1、module2、--と別のモジュールとして標準モジュールに格納しています。 各シートにはマクロ釦を配置してそのシートに対応するマクロを実行するようになっています。 現在は、初めにシート1を開いてマクロ釦を押して処理を実行後、その結果を持ってシート2に移動してマクロ釦を押して処理を実行、また次のシートに移動して処理 を順次繰り返して最終の結果が出る状況です。 この「シートを開いてマクロ釦を押す」という一連の処理を自動的に実行するマクロを作成する途中行き詰まりました。 自分の勝手なイメージでは、モジュール名を指定するとそのモジュール内の先頭のプロシージャから順番に処理されるものと思い込んでいたので、 エラーメッセージ:モジュールではなく、変数またはプロシージャを指定してください を見て、何故モジュール名でサブルーチンコール出来ないの? で思考停止に陥りました。 結論的には「application.run "Module" & i & ".Macro1"」というヒントを頂いてほぼ解決しております。 確認作業をしていたためお礼が遅くなりました。

関連するQ&A

  • エクセルマクロのCallとコンパイルエラー

    エクセルマクロのCallとコンパイルエラー よく、教えていただくのですが作ったマクロを呼び出すのに、 ・Call 作成したマクロ とか教えてもらいますが 標準モジュールのツリーには ・Module1 ・Module2 ・オートオープン ・リセット とかがあって ・Call リセット とかにして実行すると ・コンパイルエラー (モジュールではなく、変数またはプロシージャを指定してください) となってしまいます。 Callの後にはどういう風にすればいいのでしょうか? -------------- Private Sub Worksheet_Change(ByVal Target As Range) If Target.Address = "$B$5" And Len(Range("B5").Value) > 1 Then Call 印刷←印刷はModule2です。 End If End Sub ------------- で印刷のマクロの一部に Call リセット をつけたたしたらなりました。 よろしくお願いします。

  • ACCESSのVBAでのサブルーチンへの引数と戻り値について

    教えてください。 AccessのVBAで、標準モジュールに作ったサブルーチンに1つの引数を渡して、複数の戻り値(例えば「果物」を渡して、「りんご」「みかん」「いちご」をそれぞれ受け取る)を取得したいのですが、どのようにしたらよいのでしょうか? よろしくお願いします。

  • EXCEL VBAで

    VBA初心者です 簡単過ぎる質問で申し訳ありませんが 調べてみても分からなかったので質問さしてもらいます VBEの標準モジュール1で簡単なプログラムを作成しました デバッグツールバーから実行をすると プログラム通り、動作はしましたが・・・ VBE画面を閉じてからの、プログラムを実行する方法が分かりません 右上の×を押しの、プログラム実行です 作ったプログラムを動作しようと思って 開発→マクロを押しても、作ったマクロ名が表示されないです どのようにしたら、標準モジュールで作ったマクロが、表示されるようになりますか?

  • サブルーチン(共通の処理)の作り方

    VB6.0の時までは、標準モジュールやフォームモジュールにサブルーチン(共通の処理)を作って、他のフォームモジュールから呼び出しができるようになっていましたが、VisualBasic2005ではできないのでしょうか?共通のサブルーチンを作成する方法を教えてください。よろしくお願いします。

  • 隔絶されているサブルーチン間の通信の方法

    以下のようなFortranのサブルーチンとモジュールがあります。これを見ると、サブルーチンA,Bはモジュールa,bが別なのでデータ的に隔絶されていることになります。もし、このような場合、サブルーチンA,Bの間で何らかの変数を共有するようなことをしたい場合、どのような方法があるでしょうか。サブルーチンの引数を使うのは混乱の原因になりそうなので、できればmoduleの方で処理できないかと思うのですが。 混乱しそうなところなので、やり方をいろいろ比較して見てみたいと思います。Cではグローバル変数のように全体で共有する変数を用意するのかなと思いますが。 module a end module module b end module subroutine A use a end subroutin B use b end Fortranについてはここでは特設会議室はありませんが、どこかいいところがあるでしょうか。Cの専門家はいろんなことに通じていると思うのでここにお尋ねしました。よろしくお願いします。

  • UserFormをサブルーチンに出来るか

    頓珍漢な質問かもしれませんが、何分ご了承下さい。 標準モジュールで記述時、UserFormをサブルーチンとして呼び出す事は出来ないですか。 プログラムの途中に、複数項目を入力させたいのです。 InputBoxは一つしか入力させられない様だから、UserFormならと、思ったのですが。 Private付プロシージャは、同じモジュールのプロシージャからしか呼び出せないのでしょうか。 宜しくお願い致します。

  • VBAのアドインについて

    現在、エクセル2000を使用しています。  セルの”*”という文字をダブルクリックすると、ユーザーフォームが開き、テキストボックス内に文字を入力したらOK(コマンドボタン)を押すとセルにその文字が入ります。  コマンドボタンを実行すると、Call ○○○で標準モジュールのマクロを呼び出すようになっています。  このCallが10行くらい組んであり、それぞれの標準モジュールを呼び出しているのですが、ファイルが重たくなってしまいました。  この標準モジュールをアドイン化して使用できるのでしょうか?

  • EXCELのVBAについて

    エクセルのVBAでユーザーフォームに作ったテキストボックスに入力した値を、コマンドボタンによる「実行」とともに別に作った標準モジュールの変数として代入するにはどうすれば良いでしょうか? 具体的な流れは、 マクロ実行  ↓ ユーザーフォーム出現  ↓ テキストボックスに数字を代入→「実行」  ↓ 変数を代入された標準モジュールによる処理完了 というものです。 ご教授お待ちしております。

  • エクセルVBAの標準モジュール名の変更方法?

    エクセル2000です。 標準モジュールは通常Module1~ですが、この名前を変えるにはどうしたらよいのでしょう?右クリックしてもだめでした。 VBAではなく、手作業で変える方法の質問です。 よろしくお願いします。

  • Excel マクロのmodule名を変える方法

    マクロのmoduleは標準でmodule1、module2というように番号で管理されていますが、この名前を変更する方法はあるのでしょうか?

専門家に質問してみよう