★独学者が1年後にExcelVBAを爆発的に伸ばすための最低限の基礎知識メモ(ダイジェスト):Vol0059 :【番外】VBAでは間違って教えられることが多い「ステートメント」の意味やVBAの重要ポイントについて-04(訂正)
バックナンバー目次ページは→こちらです。
まぐまぐのページは以下です。
https://www.mag2.com/m/0001691660.html
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
■独学者が1年後にExcelVBAを爆発的に上達させるための最低限の基礎知識メモ(ダイジェスト)
Vol.0059
タイトル:【番外】VBAでは間違って教えられることが多い、
「ステートメント」の意味やVBAの重要ポイントについて-04(訂正)
バックナンバー目次とサンプル号
https://euc-access-excel-db.com/tips/ct07_se/ct075012_xls2k_vba_tips/mag2-01
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
こんにちは。
前回、書き間違えたところがあったので訂正です。
以下の部分が間違えたり、不足がありました。
(他の箇所もあるかもしれません。もしそうでしたらごめんなさい。
ご自分でも直してみてください。)
あと、後半に全部の「まとめ直し」もしておきました。
よろしくお願いいたします。
========================
(01)「●Functionプロシージャの重要性」のところ
●Functionプロシージャの重要性
Functionプロシージャだけが上記の「5つのパターンすべてが作れる」です。
結局、Functionプロシージャだけが、ア~オのすべてのものが作れます。
しかも、「関数名が変数の役割も兼任しています」し。
なので、いろんなタイプのFunctionプロシージャが作れることが、
(引数ありなし、既定値ありなし、既定値オブジェクト、戻り値オブジェクト、引数ByVal・ByRefなど)
「VBAのすべて」と言っても過言ではないです。
↓
↓
↓
●Functionプロシージャの重要性
Functionプロシージャだけが、「それ単独で」、上記の「5つのパターンすべてが作れる」です。
結局、Functionプロシージャだけが、「それ単独で」、ア~オのすべてのものが作れます。
しかも、「関数名が変数の役割も兼任しています」し。
Propertyプロシージャでも「5つのパターン」を作れますが、
Let、Set、Get、の3つが必要で「単独ではない」ですし、
Functionを知っていればすぐに作れる(=多分Funcrionがベースになっている)ので、
Functionのあとに学習するほうが理解しやすいです。
(また、Propertyプロシージャはプロパティ値の読み込みや書き換えが
メインのお仕事なので、Functionのように「何でもできちゃう」、
というわけでもないので…。
つまりFunctionは「その用途がPropertyプロシージャと比べるとケタ違いに広い」、
ので…。逆に言うと、Propertyプロシージャは用途が狭い…ので…。)
なので、いろんなタイプのFunctionプロシージャが作れることが、
(引数ありなし、既定値ありなし、既定値オブジェクト、戻り値オブジェクト、引数ByVal・ByRefなど)
「VBAのすべて」と言っても過言ではないです。
===========
(02)「●VBAの命令単語のカッコや名前付き引数の使い方」のところ
・プロパティ値の書き変えについては、
代入ステートメントの形で書くのが普通なので、
プロパティがPropertyプロシージャを使うセッターだったとしても、
名前付き引数については、使う場面は、基本、ありません。
(例外があるかも?ですが。未調査)
話が逸れますが、プロパティ値の書き変えについては、
プリミティブな値の書き変えなら、先頭に「Let」が省略されていますので、
「Let」をあえて付けてもエラーになりません。
「aaa=Activesheet.Range("A1")」を
「Let aaa=Activesheet.Range("A1")」と書いても
エラーにならない、という意味です。
↓
↓
↓
・プロパティの場合の「カッコや名前付き引数」についても、
「原則」、「SubやFunctionと同じ」と思ってもいいと思います。
プロパティの「カッコを付ける・付けない」の場合、
「Range "A1" .value」とカッコ無しで書くとエラーになりますが、
これを(SubやFunctionの場合と同じように)、
「戻り値を使うからカッコが必要」とか、
「式として使うからカッコが必要」と覚えてしまうと、
SubやFunctionのカッコの延長上…というか、
「同じ意味としてで」、そのまま「統一感をもって=シンプルに」理解できます。
特にプロパティの戻り値を使う場合。
前述のSubやFunctionの場合の、
『Callを使わない→→カッコを使う場合→「戻り値を使う』、
というルールにも一応、合致しています。
なので、
「あ、意識してなかったけど、実は、カッコ付加の理由は同じなんだ!」、
みたいに理解できます。
実際、クラスモジュールや標準モジュールで自作のプロパティを作ると、
Functionプロシージャに酷似しているので、そこからも、
「SubやFunctionのルールと同じと理解しても構わないのかも…」
という感覚になると思います。自分はそうでした。
戻り値を使わない場合、つまり、「プロパティ値の書き変えの場合」は、
ほんとに難しくて、こじつけ、になってしまいますが、
例えば、
『「Callが使えない、Set obj01 = CreateObject(×××)」の場合と
と似たようなもんだ… 』、
みたいに考えてしまいます。
プロパティ値の書き変えの場合、カッコを使う式が
左辺になってしまいますが・・・。
ただ、VBA的には『 Range("A1").Value 』は「式」なので、
この項の冒頭にも書いた通り、
「式として使うかどうかでカッコが決まる」、
「式として使うならカッコが必要」、
と、無理矢理あてはめてしまってもいいかも?しれません。
これも、実際に、自作のプロパティを作ると、
なんとなく許容できると思います。
「式」は普通、「型と値が決まってその戻り値が使える」、
というものだけど、「プロパティ」はその「戻り値」を、
「セッター(特にLet)」によって、『「逆設定」できてしまうという』、
「特殊なことができる」…、みたいに考えてしまってもいいかもしれません。
また、プロパティの場合の名前付き引数についても、
「Range("A1").Value」は、
「Range(Cell1:="A1").Value」のようにも書けるし、
「ActiveCell.Offset(1, 1)」は、
「ActiveCell.Offset(RowOffset:=1, ColumnOffset:=1)」とも
「ActiveCell.Offset(ColumnOffset:=1, RowOffset:=1)」とも、書けます。
ですので、
「プロパティの記述でも名前付き引数は使える」、と言えます。
なので、ここでも、
「SubやFunctionのルールと同じと理解しても構わないのかも…」
という仮説が成り立ち、実際、こちらは「完全に同じ」です。
話が逸れますが、プロパティ値の書き変えについては、
プリミティブな値の書き変えなら、先頭に「Let」が省略されていますので、
「Let」をあえて付けてもエラーになりません。
「aaa=Activesheet.Range("A1")」を
「Let aaa=Activesheet.Range("A1")」と書いても
エラーにならない、という意味です。
================================
================================
ひとまず以上です。
なので、全部をまとめ直しますと、以下のようになります。
================================
================================
VBAの「ポイント」のまとめ
●VBAの命令を分類すると、以降の5つしかありません。
『 1000個以上ある組込のVBAの全ての命令と、
すべての自作のSub、Function、Propertyプロシージャ 』
には、大別して以下の5つのパターンしかありません。
(ア)プリミティブな型の値を返す「だけ」のもの。(式の一種)
(VBA関数、プロパティ、演算子+オペランド(語弊あるかもですが)、自作関数、に多い)
(イ)何らかの動きをしつつ、同時にプリミティブな型の値を返すもの。(式の一種)
(メソッド、演算子+オペランド(語弊あるかもですが)、自作関数、に多い)
(ウ)オブジェクト型の値を返す「だけ」のもの。(式の一種)
(プロパティ、一部のメソッド、自作関数、に多い)
(エ)何らかの動きをしつつ、同時にオブジェクト型の値を返すもの。(式の一種)
(CreateObject関数、GetObject関数、各種Addメソッド、各種Openメソッド、自作関数、等々に多い)
(オ)何らかの動きをするだけで、何も返さないもの。(式じゃないモノ。)
(メソッド、自作関数、に多い)
※「値」=VBAの場合は、(a)と(b)の両方を指すことが多いです。
明確なヘルプ記述はありませんが、ヘルプ全体はそのような目線で書かれていて、
エラーメッセージその他からもわかります。
※「(式の一種)」とは、代入ステートメントの右辺にもなれるし、引数にもできる、
という意味とイコールです。
※「何らかの動き」→具体的には、プリミティブな型の値や変数の加工、演算、
検索、置換、切り出し、等々や、オブジェクト型の値の操作など、です。
オブジェクト型の値の操作とは、Excelの場合に限れば、
セル単位の検索、セル単位の抽出、セル単位の置換、ピボット操作、
その他の自動集計、条件付き書式、各種フィルタ操作、パワークエリ操作、
MicrosoftQuery操作、開く、閉じる、追加、削除、印刷、などです。
(※プログラミング的には「副作用」と呼ぶらしいです。)
※よって(邪道だとは思いますが)、関数、プロパティ、メソッド、自作関数、などの区別は、
使う場面やそれらの性格などの違いによって言い分けてるだけ・・・、と取れなくもない。
●Functionプロシージャの重要性
Functionプロシージャだけが、「それ単独で」、上記の「5つのパターンすべてが作れる」です。
Functionプロシージャだけが、「それ単独で」、ア~オのすべてのものが作れます。
しかも、「関数名が変数の役割も兼任しています」し。
Propertyプロシージャでも「5つのパターン」を作れますが、
Let、Set、Get、の3つが必要で「単独ではない」ですし、
Functionを知っていればすぐに作れる(=多分Funcrionがベースになっている)ので、
Functionのあとに学習するほうが理解しやすいです。
(また、Propertyプロシージャはプロパティ値の読み込みや書き換えが
メインのお仕事なので、Functionのように「何でもできちゃう」、
というわけでもないので…。
つまりFunctionは「その用途がPropertyプロシージャと比べるとケタ違いに広い」、
ので…。逆に言うと、Propertyプロシージャは用途が狭い…ので…。)
なので、いろんなタイプのFunctionプロシージャが作れることが、
(引数ありなし、既定値ありなし、既定値オブジェクト、戻り値オブジェクト、引数ByVal・ByRefなど)
「VBAのすべて」と言っても過言ではないです。
中でも、特に、「オブジェクトを返せるFunctionプロシージャ」や
「オブジェクトを引数にできるFunctionプロシージャ」が作れるようになると、
「学習開始から1年後くらい」に、「爆発的な上達」が「やってくる」可能性が高まります。
Propertyプロシージャも作れるようになり、結果、簡単なクラスモジュールが
すぐに作れるようになるので、それが作れることが
「VBAの真のスタートライン」となります。
また、「1年後の」「爆発的な」上達の「絶対条件」です。
初心者本を終えたら、とにかく「”オブジェクトを返す自作関数”作り」から
スタートしましょう。
●メソッドについて
クラスモジュールで自作のメソッドを作ると、
「メソッドは「Sub」か「Function」のプロシージャと同義なんだ。」
「特定のオブジェクト(クラス)に紐付いているところだけが違う」
「=オブジェクトを先に選択(取得)しないと使えない、というだけ。」
ということが理解できるようになります。
●「式」の説明。
VBA限定の「式」とは、
数値、文字列、オブジェクトのいずれかに評価できる、生の値、変数、定数、関数、
プロパティ、値を返す一部の少な目のメソッド、演算子(オペランド含む)、などの組み合わせ。
ヘルプにはそんな感じで書いてあります。
(調べたら以下の通り→式とは「文字列、数値、オブジェクトのいずれかに評価される、
キーワード、演算子、変数、定数の組み合わせ。計算、文字列の処理、
データのテストなどを行うときに式が使われます。」)
単語1語でも、複数の単語の組み合わせでも、それ全体が評価された時に型が決まり、値も決まるもの。
プリミティブな型に評価されれば単一の値が決まり、オブジェクト型に評価されれば、
決めうちできるプロパティ値のみが確定します。
よくわからないうちは、F8キーのステップ実行時に、ウォッチウィンドウで型と値が一瞬でも確定するもの、
と理解していつも観察しまくればいいです。
※C言語では単なる代入は『式』だそうです(最後にセミコロンが付かない状態)。
例えば「a=10」みたいなもの。(最後に「;」が付くとステートメントになるそうです)
JavaScriptでも似てるみたいです。
Pythonでも代入の「=」を「:=」と書くと式になるようです。
VBAだと「a=10」は「ステートメント」です。(Letを省略した代入ステートメント)
しかしながら『式』の『定義自体』は、
C言語でもVBAやPythonでもJavaScriptでも共通であり、
『評価されたときに何らかの型と値を持つものが式』
という考え方に相違はないそうです。
●VBAの命令単語のカッコや名前付き引数の使い方
※「式として使うかどうかでカッコが決まる」、
「カッコは”式にするための装置”」、
みたいに考えると整理しやすい方はそれで。
※「============」に挟まれた部分が
基本ルール・・・、みたいに覚えてみてください。
============
・SubとFunctionとPropertyプロシージャ(≒自作関数)、
・メソッド(自作と組み込みの両方)
・組み込みのVBA関数のすべて、
全部、
・「カッコを付けるルール」と
・「名前付き引数の書きかたのルール」は、
・「原則」、「全部同じ」、と
理解してOKです。
それに加えて、プロパティ(自作と組み込みの両方)の場合も、そうだとイメージしてOKです。
(あくまでもイメージです。しかも無理矢理ですが・・・。)
(ルール01)
Callを使わない→→カッコを使う場合→「戻り値を使う=代入時の右辺や引数として使う」という場合。
(代入時の右辺として、引数として、単純に戻り値として、
等々で使う時は、自動的にこの書き方になると思います。)
→→カッコを使わない場合→戻り値を使わない。逆に、戻り値が不要なときに使う。
(※メソッドの実行時で使う時は、自動的にこの書き方が多くなると思います。)
(ルール02)
Callを使う→→(ルール01)は無視される。戻り値が使えなくなる。逆に、戻り値が不要なときに使う。
原則、カッコが必須。戻り値が在ろうが無かろうが。
※注意点:引数が1つのときの「罠」
Callを使わず、戻り値も受け取らないのに、引数に無理やりカッコを付けて1つだけ渡すと、
VBAはそれを「カッコのルール」ではなく「値渡しにするための算術演算のカッコ」と解釈して
しまうそうです。
MySub (a) ・・・ a をコピーして渡す(値渡し)という意味になる
MySub a, b ・・・ 正解
MySub (a, b) ・・・ エラー(カンマがあるのにカッコで囲むと、式として成立しないため)
※本質的・厳密的、には違いますが、
「プロパティを右辺に使う場合は必ず戻り値を使うので、カッコを必ず使う…」、
みたいなイメージで、
そう無理矢理理解してしまってもいいかも?です。学習の初期段階だけは。
(覚え方としてそう覚えてしまうと統一感があってラクかも?ということです。)
※個人的には、
『 自作関数(自作のSub、Function)を呼び出す時で、かつ、戻り値不要時 』、
「だけ」に使うと、
「あ、これは自分で作ったんだ」と見やすくなるので、そこだけにCallを使うほうが
いいかなと思います。
代入ステートメントの右辺に使う時はそれができないので微妙ですが、でもそれでも。
※メソッドを使う場合は、メソッド自体が特定のオブジェクトでしか使えないSubかFunctionなので
「Call」を先頭に書いてもエラーになりませんが、その場合、カッコが必須となります。
上記の(ルール01)、(ルール02)、いずれも適用されます。
============
以下、補足です。
※一応、 Callの記述ルールは、SubとFunction、
および両方のメソッドにのみ存在します。
が、最初のうちはプロパティでも同じ、とイメージしてしまってもいいと思います。
そのほうが、カッコの記述ルールに統一感が出るので。
Propertyプロシージャでを自作のプロパティを作ると、
その意味がより理解できると思います。
※プロパティの場合の「カッコや名前付き引数」についても、
「原則」、「SubやFunctionと同じ」と思ってもいいと思います。
プロパティの「カッコを付ける・付けない」の場合、
「Range "A1" .value」とカッコ無しで書くとエラーになりますが、
これを(SubやFunctionの場合と同じように)、
「戻り値を使うからカッコが必要」とか、
「式として使うからカッコが必要」と覚えてしまうと、
SubやFunctionのカッコの延長上…というか、
「同じ意味としてで」、そのまま「統一感をもって=シンプルに」理解できます。
特にプロパティの戻り値を使う場合。
前述のSubやFunctionの場合の、
『Callを使わない→→カッコを使う場合→「戻り値を使う』、
というルールにも一応、合致しています。
なので、
「あ、意識してなかったけど、実は、カッコ付加の理由は同じなんだ!」、
みたいに理解できます。
実際、クラスモジュールや標準モジュールで自作のプロパティを作ると、
Functionプロシージャに酷似しているので、そこからも、
「SubやFunctionのルールと同じと理解しても構わないのかも…」
という感覚になると思います。自分はそうでした。
戻り値を使わない場合、つまり、「プロパティ値の書き変えの場合」は、
ほんとに難しくて、こじつけ、になってしまいますが、
例えば、
『「Callが使えない、Set obj01 = CreateObject(×××)」の場合と
と似たようなもんだ… 』、
みたいに考えてしまいます。
プロパティ値の書き変えの場合、カッコを使う式が
左辺になってしまいますが・・・。
ただ、VBA的には『 Range("A1").Value 』は「式」なので、
この項の冒頭にも書いた通り、
「式として使うかどうかでカッコが決まる」、
「式として使うならカッコが必要」、
と、無理矢理あてはめてしまってもいいかも?しれません。
これも、実際に、自作のプロパティを作ると、
なんとなく許容できると思います。
「式」は普通、「型と値が決まってその戻り値が使える」、
というものだけど、「プロパティ」はその「戻り値」を、
「セッター(特にLet)」によって、『「逆設定」できてしまうという』、
「特殊なことができる」…、みたいに考えてしまってもいいかもしれません。
また、プロパティの場合の名前付き引数についても、
「Range("A1").Value」は、
「Range(Cell1:="A1").Value」のようにも書けるし、
「ActiveCell.Offset(1, 1)」は、
「ActiveCell.Offset(RowOffset:=1, ColumnOffset:=1)」とも
「ActiveCell.Offset(ColumnOffset:=1, RowOffset:=1)」とも、書けます。
ですので、
「プロパティの記述でも名前付き引数は使える」、とも言えます。
なので、ここでも、
「SubやFunctionのルールと同じと理解しても構わないのかも…」
という仮説が成り立ち、実際、こちらは「完全に同じ」です。
話が逸れますが、プロパティ値の書き変えについては、
プリミティブな値の書き変えなら、先頭に「Let」が省略されていますので、
「Let」をあえて付けてもエラーになりません。
「aaa=Activesheet.Range("A1")」を
「Let aaa=Activesheet.Range("A1")」と書いても
エラーにならない、という意味です。
※あと、BeepやFilecopy、 などの「コマンドっぽい性格」の
「ステートメント用のキーワード」は、Callやカッコのルールは適用されません。
「コマンドっぽい」ので、「なんで?」と思うかもしれませんが、
ステートメント用のキーワードにはCallやカッコのルールは適用されません。
メソッドでもないので、オブジェクトブラウザにも出てきません。
ただ、名前付き引数は一部使えるものがあります。
例えば「Sendkeys」とか。
「SendKeys String:="^s", Wait:=True」
のように名前付き引数を使えます。
でも、関数やメソッドではなく、「ステートメント用のキーワード」です。
(※もしかしたら、カッコが使えるモノはあるのかも?調べてません。すみません。)
今回は以上です。
今回は以上です。
==========================================================================
バックナンバー目次とサンプル号
https://euc-access-excel-db.com/tips/ct07_se/ct075012_xls2k_vba_tips/mag2-01
----------------------------------------------------------------------
■独学者が1年後にExcelVBAを爆発的に上達させるための最低限の基礎知識メモ(ダイジェスト)
発行システム:『まぐまぐ!』 http://www.mag2.com/
配信中止はこちら https://www.mag2.com/m/0001691660.html
----------------------------------------------------------------------