● Access2000VBA・Excel2000VBA独学~あるプロシージャから別のプロシージャを呼び出す方法の概要(共用部品・自作関数を作るために)~
※まだ書きかけです。すみません。
※間違ってたらすみません。
※メモ書きなので、自分でも意味不明な箇所も多いです。ごめんなさい。
目次
★ はじめに
★ VBAの「短期間の中級以上への上達」と密接に関係すること
★ ※おまけ(関連)「オブジェクトと自作関数(特にオブジェクトを返す自作関数)」のことが分かることで
できるようになること。
※同名のプロシージャを複数作ってしまった場合の注意
★ 呼び出し構文
★ 事例
(01)シートやブックのモジュール、標準モジュールのプロシージャから、「標準モジュールのプロシージャ」を呼び出す
(02)シートやブックのモジュール、標準モジュールのプロシージャから、「シートモジュールのプロシージャ」を呼び出す
(03)シートやブックのモジュール、標準モジュールのプロシージャから、「ブックモジュールのプロシージャ」を呼び出す
(04)シートやブックのモジュール、標準モジュールのプロシージャから、「シートモジュールの”イベントプロシージャ”」を呼び出す
(05)シートやブックのモジュール、標準モジュールのプロシージャから、「ユーザーフォームの”イベントプロシージャ”」を呼び出す
(06)あるユーザーフォームのプロシージャから、 「別のユーザーフォームのプロシージャ」を呼び出す
(07)Accessで、その中で、どこかのプロシージャから、「どこかのフォームのコマンドボタンのイベントプロシージャ」を呼び出す
(08)Acccessのプロシージャから「Excelのユーザーフォームのイベントプロシージャ」を呼び出す
(09)Excelのプロシージャから「Accessのフォームなどのイベントプロシージャ」を呼び出す
※Shift+TABキー、もしくは、Homeキー、Homeキー+TAB数回、を押すと、目次付近に戻れます。
SubプロシージャやFunctionプロシージャの呼び出し可能方向(実行できる場所・方法)について.pdf
↑↓ Ctrlキーを押しながらマウスのホイールを回して、拡大して見てみてください。
文字がおおきくはっきりと見えてきます。
★ はじめに
Excelに限らず「VBA」では、
「あるプロシージャからあるプロシージャを呼び出して実行する。」
ということができます。
これはSubプロシージャでもFunctionプロシージャでも同じです。
※補足:用語と概要の説明
※「プロシージャ」→VBAプログラムの最小単位です。
Subプロシージャ、Functionプロシージャ、Propertyプロシージャがあります。
「イベントプロシージャ」はSubプロシージャの仲間です。
※「Subプロシージャ」→メインプログラムのような意味合いであることが多い
プログラムです。Excel・Word・Accessではマクロのメニューから呼び出したり、
リボンやクイックツールバーにボタンとして登録することができます。
※「Functionプロシージャ」→「Subプロシージャ」などから呼び出すことが多く、
ワークシート関数のような役割も果たすプログラムです(独立するものも多い)。
なお、「値やオブジェクトを返す自作関数」を作るには、「Functionプロシージャ」
でないと作成できません。それと、ExcelやWordでは、マクロのメニューから
呼び出したり、クイックツールバーにボタン登録することが「できません」。
Accessではできます(マクロの意味合いが少し違うせいか)。
ちなみに、ExcelでもWordでもAccessでも、リボン(アドインタブ)や古いバー
ジョンのツールバーには、Functionプロシージャをボタンとして登録すること
ができます。(VBAを使うケースが多いですが。こちらやこちらをご参照下さい。)
※「Propertyプロシージャ」→「オブジェクト」を自作するときに、その中に内包させ
る「プロパティ」を自作するためのプログラム。
※ついでに「モジュール」→関連性の深い複数のプロシージャをまとめるための
いわば「白紙」です。プロシージャを複数、書くための場所、です。
基本、1つの「モジュール」の中には、複数のSubプロシージャやFunctionプロシー
ジャたち、が、混在しています。
このとき、たとえば・・・、
Subから → Sub、
Subから → Function、
Functionから → Sub、
Functionから → Function
・・・といった方向性で呼び出しが可能です。
(それぞれの頻度は別として。多いのは、Subから→Function、Subから→Sub、のケースでしょうか・・・。なお、呼び出し先が「Sub」の場合、それが「イベントプロシージャ」と呼ばれる種類のプロシージャだと、既定ではエラーになってしまうので、その場合は少し細工をしてから呼び出します。)
例えばExcelの場合、「個人用マクロブック=Psersonal.xlsb(あるいはxls)」も、その性質が利用されています。(どのxlsx、xlsmからでも、その中身を見ることができます。)
個人用マクロブックに書かれたプログラムは、「どのExcelファイルのどのモジュールのプロシージャ」からも呼び出すことができます。
(また、xlsx拡張子のファイルにはマクロは作れませんが、ただし、Psersonal.xlsbまたはPsersonal.xlsに書かれたプログラムだけは、どのxlsxファイルからでも、「作ったり書き換えたり動かしたりする」ことができます。)
もちろん、このような性質は、Accessなどの他のMicrosoft Officeのソフトでも同じです。
(ただ、ExcelとAccessでは若干作法が違いますので少し注意や慣れが必要です。)
いずれにしましても、このことについて事前に知っておくと・・・、
「どこからも呼び出せる共用部品を作る」とか、
「すでに作ったプログラムを別の場所からも再利用する」とか、
「(実際にはイベントが発生していなくても発生したかのごとく)イベントプロシージャを強制的に動かす(=実行する)ことができるので、そのような形でそれを流用することで同じプログラムを書く手間を省く」とか、
・・・そういったことができるようになりますので、とても効率が上がります。
初心者のころはなかなか理解できないかもしれませんが、でも もし、「VBAの上達をしたい」という決意のある方は、初心者のうちからでも頑張って、この、
「あるプロシージャからあるプロシージャを呼び出して実行する。」ということと、
ついでに
「値を返す自作関数とオブジェクトを返す自作関数を作る。」ということをぜひ学んでください。
★ VBAの「短期間の中級以上への上達」と密接に関係すること
前項に書いた、
「あるプロシージャからあるプロシージャを呼び出して実行する。」ということと、
「値を返す自作関数とオブジェクトを返す自作関数を作る。」ということの2つ・・・、
これらは、絶対にはずせないので、この2つのことについては、しっかり学んでおいてください。
ヘルプやオブジェクトブラウザを読んだり、ヘルプとオブジェクトブラウザの連携技を理解する、自作のオブジェクトやプロパティ、イベント、などを作る上でも絶対に欠かせません。
基本、VBAは「オブジェクトと自作関数」のことが分からないと、100%、上達しません。
また、エラー解決についても、いつまでたっても、「自力で解決できない」という状況が続いてしまいます。
ですので、この2つのことは、「分かるまで」「分かる人に」「何百回でも」聞いて、必ず自分のモノにしてください。ここを必ずモノにできれば、お金を払って習ったとしても、比較的早く、その費用を回収できるでしょう。
逆に、これをやるつもりがない人は(特にタイムイズマネーやコストを重視する方は敢えて)、やるだけ時間の無駄なので、もうVBAは自分ではやらずに、いかに他人に安くやっていただくか、を考えてください。腕のいい学生さんなどを見つけて安くやっていただくほうがはるかにお仕事のためになります。(ただしその場合は、もしできるなら、VBAができるだけの人よりも、MicrosoftQueryとピボットが扱えて・かつ・それとグラフがVBAで自在に動かせる人のほうがコストを安く作ってくれますので=重宝しますので、そういう人を見つけるようにしてください。AccessなどやMicrosoftQuery+ピボット、COMオートメーションやSQLが使えず、単にExcelVBAしかできない人は、ビジネス定型集計にまで無駄なVBAや関数を多用してかえってデータ管理のムリ・ムダ・ムラを生みだす確率が高いですので・・・。)
というわけで、「あるプロシージャからあるプロシージャを呼び出して実行する。」といった場合、どんな風に呼び出すのか、を、その概要を、以降で、ミニ実例で説明します。
★ ※おまけ(関連)「オブジェクトと自作関数(特にオブジェクトを返す自作関数)」のことが分かることでできるようになること。
(a)オブジェクトブラウザの画面の本当の意味と、使い方がわかるようになる。
(b)ヘルプがおおむね自力で読めるようになる。
(c)(a)と(b)の、2つを連携させた技が、これまでの数倍は活用できるようになり、結果、さらに、2つのことの理解が深まりやすくなる。
(d)(a)~(c)が理解できているので、Web記事や市販書籍が「これまでの数倍は簡単に目に映る」ようになる。読める。
(e)同様に、マイクロソフトの技術情報も、「これまでの数倍は簡単に目に映る」ようになる。読める。
(f)同様に、イミディエイトウィンドウ、ローカルウィンドウ、が、「これまでの数倍は活用できる」ようになる。
(g)(a)~(f)が理解できているので、つまらないエラーをする頻度が減る
(h)(a)~(f)が理解できているので、つまらないエラーをしても今までの数倍は早く解決できる
(i)同様に、そこそこ入り組んだエラーも今までの数倍は早く解決できる
(j)同じプログラムを何度も書かずに共用部品としてつくれるので、効率が上がる
(k)共用部品化できることで、同じプログラムを何度もコピペしなくても済むので、メンテや作り変えがラクになる。
(l)結果、中級の上、くらいのところまで、独学でも比較的短期間に、行ける。
(m)もしお金を払って習っていれば、すぐに、費用を回収できるくらいになれる。
※以上は、当サイトで言っています、
「オブジェクトモデルの階層構造全図」
「オブジェクトの持つ5つの大きな機能」
「値やオブジェクトを返す自作関数の作成」
「共用部品の作成」
などを理解し、ヘルプとオブジェクトブラウザを「しょっちゅう使う」ようになれれば、の話です。
「オブジェクトモデルの階層構造全図」にて構造の概要をつかみながら・イメージしながら、
ヘルプとオブジェクトブラウザを「実際にしょっちゅう使う」ようになれなければダメです。
Web情報ばかりに頼っている状況下では、ダメだと思います。
重要なことは、ヘルプとオブジェクトブラウザ、に、相当、書いてあります。
(Webや市販書籍には表面だけの、誤解しやすい記事も多いので。ヘルプが万能というわけではありませんが 誤訳もあるそうで、信じきるのもいけないかもしれませんが、でもそれでも、「ヘルプとオブジェクトブラウザ」が、「腐っても鯛」、「1stCall」、なのは間違いないです。)
=============================
Call VBAProject.モジュール名.プロシージャ名
(Call オブジェクト式.プロシージャ名)
例
Call VBAProject.Module1.KokyakuIdGet01
(KokyakuIdGet01 は架空のプロシージャ名です。)
※呼び出し先が「標準モジュールに書いてある Subプロシージャ」の場合、「Sub」よりも前(先頭)に「Private」がついていると、リボンの「マクロ」メニューからは呼び出せませんが、他のプロシージャからは呼び出せるっぽいです。(ただし、『 Call VBAProject.モジュール名.プロシージャ名 』、といった感じで、オブジェクト式を省略しない形でCallした場合のみっぽいです。プロシージャ名だけでは呼び出せないっぽいです。)
※「VBAProject.」や「Module1.」(いずれもドット含む)の部分は省略可能ですが、「VBAProject」の仕組み・概要・オブジェクトモデル階層構造全体図の中での位置関係等々がわかるまでは省略しないほうが無難です。(忘れたころに読み返すと、目印になってコードの読み返しがしやすくなるのもあるし。)
ExcelVBAだけでなく、AccessでもWordでも同じですが、省略する方法しか知らないとすぐに壁にぶち当たります。
そもそも「省略」とは、理解できている人がやることであって、理解していない人がやることではありません。理解していない人がやると単なる手抜き・かつ・エラーの原因にしかなりません。
ExcelVBAで多くの独学者が挫折するのは、「省略しない正式な書き方」をしつこく教えるサイトや本が少ないからです。、いわば「手抜き」ばかり教えられるからです。「手抜き」は本質を理解しないまま進む、ということです。(って偉そうにいえないけど、でも、僕もそれにハメられました。ExcelVBAは多くのサイトや書籍で、相当、手抜きして教えられているな~。そりゃ挫折するわ。教えてもらえてないもん。と感じています。)
初心者のうちは、「ムダ・冗長」とわかっていても、あえて、省略しない書き方を多く学ぶべきだし、教えるほうが教えてないのが非常にいけないと思います。もし有料で習って手抜きされたら(省略しない書き方をしっかり時間をとってカリキュラムとして一度も教わらなかったら)、金返せと言ってもいいでしょう。絶対に上達しません。
※「Module1」などの「モジュール名」は、Nameプロパティで取得できる名前でなくて、「CodeName」プロパティで取得する名前です。
※SubプロシージャでもFunctionプロシージャでも、引数が必要な場合は引数も書く必要があります。
※「Call」は省略できる場合もありますが、しないほうがエラーやトラブルが無いです。
※標準モジュールに書かれたプロシージャは、「モジュール名」を省略しても呼び出せます。が、仕組みがわかるまでは省略しないほうが無難です。
※他方、シートモジュールやブックモジュールに書いたプロシージャを呼び出すには、「モジュール名」を省略しないで書かないと多くの場合エラーになります。ただし、同一のモジュール内に書かれたプロシージャを呼び出すときだけは、「モジュール名」は省略でき、エラーにはなりません。例えば「Sheet1」というシートモジュールに書かれたプロシージャを、同じく「Sheet1」に書かれた何らかのプロシージャから呼び出すときだけは「モジュール名」を省略してもエラーにはなりません。
※引数の無いイベントプロシージャは簡単に呼び出して強制実行させられます。
※引数のあるイベントプロシージャは引数に値や式を指定しないとエラーになりますが、半面、指定さえしてしまえば、それがダミー的な値・一時的な値でも呼び出せる=動くことが多いです。
※同名のプロシージャを複数作ってしまった場合の注意
例えば任意のプロシージャから「test01」というプロシージャを呼び出したい場合、通常、「Call test01」という形で「モジュール名を省略した書き方」で呼び出せるわけですが、その場合は基本、「標準モジュール」に書かれた「test01」プロシージャだけが自動的に呼び出される決まりになっています。
シートモジュールやブックモジュールに「test01」プロシージャが書かれていたとしても、それは呼び出されません。
ただし、このとき注意が必要なのは、『 ”標準モジュール” に、同名のプロシージャを複数作ることができてしまう。 ”各モジュールごとに” 作ることができてしまう・・・』という点です。(そして、単独で作ったり実行したりするだけならエラーになりません。)
例えば、標準モジュールに「Module1」「Module2」「Module3」・・・と複数の標準モジュールを作ってあった場合、それぞれに「test01」というプロシージャを作ることができてしまいます。
なので、もし、そのように複数の標準モジュールに同名のプロシージャを作ってしまった場合は、
「Call Module1.test01」とか、
「Call Module2.test01」とか、
「Call Module3.test01」といった感じで、
どのモジュールの「test01」プロシージャかを明示的に指定する必要があります。
(Module1、とか、Module2、とか、Module3、のことを、「モジュール名」と呼んだりします。)
指定しないと、「名前が適切ではありません」というエラーになります。
逆に言うと、そういうエラーになるのが面倒くさいので、プロシージャ名は最初から「すべて異なるプロシージャ名をつけるほうが無難」、ということになります。
(「名前が適切ではありません」エラーが出たら、同名のプロシージャ名が無いかを疑います)
これはSubプロシージャでもFunctionプロシージャでも同じです。
=============================
※呼び出し先のプロシージャに引数(ひきすう)が必要な場合は、その引数も指定します。
引数とは、何かの命令を実行するときに必要とされる、「条件値」などのことです。
※呼び出し先のプロシージャがSubプロシージャでもFunctionプロシージャでも同じです。
(01)シートやブックのモジュール、標準モジュールのプロシージャから、「標準モジュールのプロシージャ」を呼び出す
「Sheet1」などのシートモジュールや「ThisWorkbook」のブックモジュール、あるいは、標準モジュールの各プロシージャから、「Module1」という標準モジュールの中の「test01」というプロシージャ(Sub、あるいはFunctionを)を呼び出して実行する例です。
Call VBAProject.Module1.test01
Call Module1.test01
Call test01
※標準モジュールに書かれたプロシージャは、「モジュール名」を省略しても呼び出せます。が、仕組みがわかるまでは省略しないほうが無難です。(目印になってコードが読み返しやすくなるので。)
※同様に、「VBAProject.」も省略可能ですが、こちらも、「VBAProject」の仕組みやオブジェクトモデル階層構造全体図の中での位置関係等々がわかるまでは省略しないほうが無難です。
※「Module1」などの「モジュール名」はNameプロパティで取得できる名前でなくて、「CodeName」プロパティで取得する名前です。
※シートモジュール、ブックモジュールは、イベントプロシージャや、それらの各モジュールに関係の深いプロシージャを書く場所です。
(02)シートやブックのモジュール、標準モジュールのプロシージャから、「シートモジュールのプロシージャ」を呼び出す
同じくシート・ブック・標準モジュールのプロシージャから、「Sheet2」というシートモジュールの、「test01」というプロシージャ(Sub、あるいはFunctionを)を呼び出して実行する例です。
Call VBAProject.Sheet2.test01
Call Sheet2.test01
※シートモジュールやブックモジュールに書かれたプロシージャは、モジュール名を明記しないと呼び出せません。
(03)シートやブックのモジュール、標準モジュールのプロシージャから、「ブックモジュールのプロシージャ」を呼び出す
同じくシート・ブック・標準モジュールのプロシージャから、「ThisWorkbook」というブックモジュールの、「test01」というプロシージャ(SubでもFunctionでも)を呼び出して実行する例です。
Call VBAProject.ThisWorkbook.test01
Call ThisWorkbook.test01
(04)シートやブックのモジュール、標準モジュールのプロシージャから、「シートモジュールの”イベントプロシージャ”」を呼び出す
同じくシート・ブック・標準モジュールのプロシージャから、「Sheet2」というシートモジュールの「CommandButton21_Click」というイベントプロシージャを強制実行する(=呼び出す)例です。
まず、事前措置として、「Sheet2」というシートモジュールの「CommandButton21_Click」プロシージャの、先頭の「Private」を「Public」に書き換えます。
その後、以下のコードでそのイベントプロシージャを(イベントが発生してなくても)強制的に呼び出して実行させることができます。
Call VBAProject.Sheet2.CommandButton21_Click
Call Sheet2.CommandButton21_Click
Call Application.Workbooks("Book1").Worksheets("Sheet2").CommandButton21_Click
Call Application.Workbooks(1).Worksheets(2).CommandButton21_Click
Call Application.Workbooks(1).Sheets(2).CommandButton21_Click
例えばですが、「ここにこの値が入力されたときは、そことあそこのボタンが押されたことにしてしまいたい。そうすれば無駄なプログラムを書かずに済むよね?」といった場合などに、使えることがあります(エラーで使えない場合もたまにありますが)。
つまり、過去に書いたプログラムの文字通り、再利用・流用、です。
たとえば、検索の自動化、などです。
たとえば『検索語句を検索語句のテキストボックスに自動的にセットして、あとは「検索ボタン」が押されたことにしてしまいたい』・・・、といったようなケースです。
実際には検索ボタンが押されなくても、押されたことにしてしまえる・・・ということです。
「ThisWorkbook」のイベントプロシージャを呼び出す場合もやり方は同じです。イベントプロシージャの、先頭の「Private」を「Public」に書き換えてから処置します。
※シートモジュール、ブックモジュールは、イベントプロシージャや、そのれらのモジュールに関係の深いプロシージャを書く場所です。
※イベントプロシージャを強制的に呼び出す場合で、正しいコードで呼び出しているはずなのにエラーになる場合は、多くは、イベントプロシージャに引数が設定してあると思います。(Publicに書き換え/書き足ししたプロシージャの、まさに書き換えたその行のカッコの中に。)
その場合は、呼び出し側(Call の側のコード)に、カッコと該当引数の値も書いてあげます。
もし引数がわからなかったら、適当なダミーの値でもいいので、引数が要求している型のデータを呼び出し側(Call の側のコード)に書いてあげます。
それで動くことがちょくちょくあります。
(05)シートやブックのモジュール、標準モジュールのプロシージャから、「ユーザーフォームの”イベントプロシージャ”」を呼び出す
同じくシート・ブック・標準モジュールのプロシージャから、ユーザーフォームのイベントプロシージャを強制実行する(=呼び出す)場合です。
基本的には前項の(04)と同じですが、ユーザーフォームの表示設定が「モーダル」になっているとダメっぽいです。(=ユーザーフォームの「ShowModalプロパティ」が「True」になっているとダメっぽいです。)
逆に、ユーザーフォームの表示設定を「モードレス」にすれば、(04)と同じ要領でコマンドボタンなどのイベントプロシージャが呼び出せるっぽいです。
「モードレス」にするには、ユーザーフォームの「ShowModalプロパティ」を「False」にします。(当方のテストではそれで動きました。)
(06)あるユーザーフォームのプロシージャから、 「別のユーザーフォームのプロシージャ」を呼び出す
あるユーザーフォームのプロシージャから、 別のユーザーフォームのプロシージャを呼び出す場合です。
基本、前項の(04)(05)と同じと思われます。(僕はやったことありませんけど)
(07)Accessで、その中で、どこかのプロシージャから、「どこかのフォームのコマンドボタンのイベントプロシージャ」を呼び出す
Accessで、その中で、どこかのプロシージャから、どこかのフォームのコマンドボタンのイベントプロシージャを呼び出す場合です。
基本、Excelの(04)と同じです・・・
ただ、Publicを書くことは覚えていますが、モーダル・モードレスのことは忘れました。
どっちゃでもできたような・・・
間違っているかもしれないので、ご自分でも実際に動かして調べてみてください。
(08)Acccessのプロシージャから「Excelのユーザーフォームのイベントプロシージャ」を呼び出す
AcccessのプロシージャからExcelのユーザーフォームのイベントプロシージャを呼び出す場合です。
詳しくは書きませんが、「COMオートメーション」と呼ばれる機能を使うとできます。
その際は「参照設定」というものをするか、それと同等のプログラムを書くこと、および、SETを使ったExcelブック(またはユーザーフォーム)のオブジェクト変数への代入等々が必要です。
それが完了すれば、基本、(04)(05)と同じです。
詳しくはまたどこかで・・・。
(09)Excelのプロシージャから「Accessのフォームなどのイベントプロシージャ」を呼び出す
ExcelのプロシージャからAccessのフォームなどのイベントプロシージャを呼び出す場合です。
基本、(07)(04)と同じです。
こちらも、詳しくはまたどこかで・・・。