★独学者が1年後にExcelVBAを爆発的に伸ばすための最低限の基礎知識メモ(ダイジェスト):Vol0050:すべての基本(ヘルプ読解含)。「自作関数」について03 ~ 「VBAの悪しき”省略”について一部を少し・・・」「Let」「ByVal」「ByRef」
バックナンバー目次ページは→こちらです。
まぐまぐのページは以下です。
https://www.mag2.com/m/0001691660.html
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
■独学者が1年後にExcelVBAを爆発的に上達させるための最低限の基礎知識メモ(ダイジェスト)
Vol.0050
タイトル:★独学者が1年後にExcelVBAを爆発的に伸ばすための最低限の基礎知識メモ(ダイジェスト):Vol0050:すべての基本(ヘルプ読解含)。「自作関数」について03 ~ 「VBAの悪しき”省略”について一部を少し・・・」「Let」「ByVal」「ByRef」
バックナンバー目次とサンプル号
https://euc-access-excel-db.com/tips/ct07_se/ct075012_xls2k_vba_tips/mag2-01
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
今回は「VBAの悪しき”省略”について一部を少し・・・」です。
「Let」「ByVal」「ByRef」というキーワードなどの「悪しき”省略”」について、
少しお話をします。
そのほか、それに関係して「値型データ」や「参照型データ」・・・、といった、
「(VBAを含む)オブジェクト指向プログラミング」における、
「超」「重要」な用語や、
そのほか、VBAに限定されますが、
「Set」
「Property Let プロシージャ」
「Property Set プロシージャ」
「Property Get プロシージャ」
といった用語について、
あるいは、
「=」って代入と比較のどっちの意味?
「変数を1文字だけで書く」ということの弊害
「省略(短く書けること)」が「カッコイイ」というクズさ、バカさ加減
などについても、
「ほんの」「ほんの」「少し」だけ、
触れていきます。
==============
で、早速ですが、
今回の「z関数」の場合、以下のようなプログラムコードなのですが・・・・、
Function z(x As Long, y As Long) As Long
Let z = x + y
End Function
このなかで「Let」というキーワードですが、通常は「省略」されます。
つまり、今回の「z関数」の場合、以下のように書くほうが「普通だ」ということです。
Function z(x As Long, y As Long) As Long
z = x + y
End Function
今回はこのことを入り口に、「VBA教育界の悪しき”省略”について」、
その一部をほんの少しお話したいと思います。
(VBAは悪しき”省略”がたんまりとあるので)
ではまず、「値」、というものについてです。
何度も書いてきましたが、また書きます。
「オブジェクト指向プログラミング」の場合、多分、「超」、重要な「基礎」ですので・・・
基本、
VBAに限らず、
「オブジェクト指向プログラミング」の場合、基本的には、
「値」≒「データ(≒生データ)」というものについては、
「大別して」
(A)「文字系の一般データ(プリミティブな型のデータ。プリミティブ=基礎的な、の意味です)」
と
(B)「オブジェクト」
の、
「2つのタイプ」があります。
(A)の「文字系の一般データ(プリミティブな型のデータ。プリミティブ=基礎的な、の意味です)」は、
文字列、数値、日付、Ture/Falseの論理値・2値、などの、
「文字系の」データのことを指します。
VBAの場合、そのデータ型は、
String型、Integer型、Long型、Double型、Date型、Boolran型、・・・・その他諸々・・・・、
といった感じになります。
(VBAではこの内容。他の言語ではまた違った内容になります。)
(※初心者の方には、「型」といきなり言い出してすみません。今はまだ「ふーん」でOKです。)
一方、
(B)の「オブジェクト」は、
「3D的=立体的」な「装置、ユニット」のイメージの、
「設定値とプログラムの集合体」、です。
(=「オブジェクト」とは、
特定の、「限定的な機能」を有した「プログラム集」のこと。
=ある処理・目的に特化した限定的なプログラム集。
=単なる「プログラム集」を、「3D的=立体的」な「装置、ユニット」に見立てた、
「たとえ話」。
=「オブジェクト」とは、実在しない「例え話」です。
(PCの中には実際には存在しないけれど、あるかのように例えた話・・・、
という意味です。)
=「オブジェクト」という用語は、
PCの中に文字として実在する「クラス(=プログラムコード)」と
同じく(クラスを設計図に生成命令を出し)PCの中の「メモリの中」に
実在する「インスタンス(=デジタルデータ)」をの両方をひっくるめて、
総称的に代表的に呼称したものが、「オブジェクト」だ・・・、
と、とらえるといいと思います。特に「VBA限定」では。
他の言語ではそういう考え方の言語もあるし、少し異なった考え方の
言語もあります。
ただし、オブジェクト=クラス(=クラスモジュール)だ、という
書籍や記事もあります。なので、それはそのまま受け入れても
間違いではありません。
でも、クラスモジュール=プログラミングの基本がわかるまでは、
「初心者の方は混乱するから」、
「オブジェクトという用語を使わないほうがいい」、とか
「”実在する”クラスとインスタンスという用語だけを使うにとどめたほうがいい」、
という意見もあります。
いずれにしましても、ちゃんとしたことがわかるまでは、
「オブジェクトとは、クラスとインスタンスの両方を代表的に総称した用語」、
という捉え方で問題ないです。
=ちなみに、なぜ「オブジェクト化するのか?」というと、
「プログラムを扱う効率が、すごく良くなるから」です。
例えば、ある装置の、「コア部分は同じで、2か所だけ新機能を加えた、
いわばマイナーチェンジ的な装置を作りたい」となったとき、
一から造らなくても済みます。
既存の装置をもとにして、そのコア部分はコピーしてしまい、
古い機能を削り、新機能の部分だけ追加すればOKです。
(もちろん、
マイナーチェンジ「前」の装置=オブジェクトも、
マイナーチェンジ「後」の装置=オブジェクトも、
「両方を適材適所で・今後も使っていく」という前提です。)
また、エンドユーザーが操作ミスをしないように、とか、あるいは、
「好き勝手にやりたい放題させない(壊れちゃうといけないから)」とかの意味で、
必要以上にエンドユーザーに中身を公開せずに、「隠す」ということもできます。
そのほかにも、更に効率がよくなる、とか、
「2度手間という2度手間を究極に減らせる」、
といったメリットがあります。
「もしオブジェクト化」ができなければ、それらを(同じようなものが既に
あるのに)一から全部作り直したり、バラバラに散らばったプログラムが
どうこにどう存在するかもいちいち調べないといけなくなるなるので、
非常に効率が悪く、「こんな面倒なこと、もう、やってらんない!!」、
となります。
「オブジェクト化」=「装置化」すれば、ユニットごとに事前に備わった機能を
すぐに使えるので、どの関連プログラムがどこにあるかも、いちいち調べなくても
済みます。とても、「プログラムを作る・管理する効率が」良くなります。
VBAの場合だと、「標準モジュール」で部品化・装置化をするよりも、
「よりもっと、更に効率よく」、「部品化・装置化」が可能となります。
なので、「オブジェクト化」、をします。)
VBAの場合、そのデータ型は、
Workbook型、Workbooks型、Sheets型、Worksheets型、Worksheet型、Range型、Chart型、・・・
といった感じになります。
(こちらもVBAではこの内容。他の言語ではまた違った内容になります。)
(※なお、VBAの場合、クラスモジュールを作った場合は、
つまり、「自作のオブジェクトを作った場合は」、
クラスモジュールの名前がそのまま「型」の名前となります。
他の言語も、もしかしたらそうかも?・・・しれません・・・。
でも未確認なのでご自分でも調べてみてください。)
で、
VBA以外のプログラミング言語では、
「文字系の一般データ(プリミティブな型のデータ。プリミティブ=基礎的な、の意味です)」
のことだけを
「値」
と呼び、
「オブジェクト」のことは、
「オブジェクト」、と呼ぶ、
そういうプログラミング言語があります。
でも、VBAの場合は、
「文字系の一般データ(プリミティブな型のデータ。プリミティブ=基礎的な、の意味です)」も、
「オブジェクト」も、
「両方とも」が、
「値」に、
「含まれ」ます。
VBAで「値」といったら、
大別して、
「文字系の一般データ」のことや、
「オブジェクト」のこと、
その「2つとものこと」を指します。
2007や2010のヘルプにはそう書いてあります。
それはウォッチウィンドウの「値」の列でも確認できます。
※補足
「文字系の一般データ」はプログラムコード上では、
「リテラル値」や「リテラル値+型宣言文字」というもので表現されます。
「オブジェクト」は同様には、
「オブジェクト式」や「オブジェクトを返す関数など」というもので表現されます。
なお、オブジェクトには「リテラル値」は存在しません。
まあ、何にしましても、
「VBAに限らず」、
「オブジェクト指向プログラミングに」においては、
「値」≒「データ」、
には、
「大別して」、
「文字系の一般データ(プリミティブな型のデータ)」と
「オブジェクト」の
「2つしかない」、
ということはとても重要です。
そして、VBAでもそうなっている・・・・、
(※2つを合わせて「値」と称しはしますが。)
ということは、
「本当に」
「皆さんが思う以上に」
「重要」
です。
そう考えないと、VBAで「超大切な」「ウォッチウィンドウ」も読めなくなってしまいます。
また、VBAを学習後、他の言語にも移りたいときも、移りにくくなってしまいます。
(繰り返しになりますが、他のオブジェクト指向のプログラム言語でも、大別すると、
呼び方やくくり方は異なっても、結局は、
一般データとオブジェクトしか無いので。恐らく。Pythonとか、JAVAとか。
なお、言語によっては、
「一般データ」を「値型のデータ」や「プリミティブ型のデータ」と呼び、
「オブジェクト」を「参照型のデータ」と呼ぶこともあるようです。
JAVAとかはそうみたいです。)
ちなみに、
これまでVBAを教えてきたレジェンドやそのチルドレン、出版社の人たちは、
こういう「超重要な基礎」を、
「まったく」、
「教えない」でおいて、
「逆引き辞典」のような、
「行きあたいばったり」の、
「絆創膏プログラミング」「ばかり教える」、
というか
「それしか教えない」ので、
VBAから他の言語に移った人は、
最初からつまづくことになったり、
他の言語の学習者から、
「基礎を知らないバカ扱い・クズ扱い」を受けることになります。
(そりゃそうです。
こういうことも知らないせいで、
オブジェクト指向プログラミングの「真の基礎」の、
「クラス(VBAの場合クラスモジュール)もまったく作れないわけですから…。)
なので、ここで、是非、以下のように覚え直してください。
◆「VBA」とは、
◆大別して「文字系の一般データ」と「オブジェクト」の、
◆その2つのデータを、
◆「値」と称して変数に代入し、
◆そして、その変数を操作して、
◆「自動化を実現する」・・・、
◆そういうプログラミング言語・・・、
◆です。
◆(その際、
◆ 「文字系の一般データ」は「リテラル値(型宣言文字含む)」などで表現され、
◆ 「オブジェクト」は「オブジェクト式」で表現されます。)
あるいは、
もしご自分なりの定義が作れるなら、それを使ってください。
長々と前置きをすみません。
で、
問題の「Let」ですが、
この「Let」は、
「文字系の一般データ(プリミティブな型のデータ)」を
「変数に代入するとき」に使用するキーワード(予約語)です。
※予約語=VBAの中にあらかじめ組み込まれた、
「すべての」「命令単語や定数や列挙など」のことを指す用語です。
VBAだけでなく、他のプログラミング言語でもそれは同じです。
一方、
「オブジェクト」を何らかの変数に代入する場合は「Let」は「使いません」。
「オブジェクト」の場合は「Set」という命令単語を使います。
なので、今回の「z関数」は、「Let」を省略せずに、
Function z(x As Long, y As Long) As Long
Let z = x + y
End Function
と書いて皆さんにご紹介しました。
で、
早速、横道に逸れます・・・・。
(初心者の方、ごめんなさい!!「よくわからんけどそういう話もあるのか」とご理解ください!)
で、
もう一度言います。
この「Let」は、
「文字系の一般データ(プリミティブな型のデータ)」を
「変数に代入するとき」に使用するキーワード(予約語)です。
「代入」
「するとき」
なんです。
ということはですよ?
「代入する」「とき」ってことはですよ?
つまり、
「代入ってこと」はですよ?
「z関数」の名前である「z」は、
ある意味「変数」に「似たモノ」・・・
ともとれないでしょうか?
だって、(繰り返しになりますが)
「Let」は、「変数に文字系の一般データ代入する」とき「だけ」しか使わない命令単語・・・、
なのですから。
そして「z」は
『「代入」できてしまうもの・・・』、
なわけですから・・・。
そして実際、現実に(くどくてすみません!)
「Let」を使って、「z」に「x+y」の計算結果を「代入」しているのですから。
VBAでは
このような、
「関数の名前が」
「変数のような働きも兼ねている」
とか、
「関数の名前に」
「代入できる仕様になっている」
ということが(=そういう動きが)、
「すごく」、
「すごく」、
「重要」、
です。
それがわかると、
クラスモジュールの「プロパティ」がすぐに作れるようになります。
特に、
「Property Let プロシージャ」や
「Property Set プロシージャ」、
「Property Get プロシージャ」で作る、
「自作のプロパティ」が。
「プロパティ」って、実は、
本当は「オブジェクト(≒クラス)が所有する”変数(設定値。)”」のことなんですが、
(他の言語では「メンバ変数」とも呼んだりします)
でも、
「Property Let 、Property Set 、Property Get 」のプロシージャで作るタイプの、
そういうタイプの「自作のプロパティ」の場合は、
その作り方が、
「Functionプロシージャ(≒自作関数)とかなり似た感じで作るため」、
『「関数」と同じ!』、というようなイメージに見えてくるかもしれません。
(僕は最初、そう思っていました。
今でも大雑把にそう説明することが多いです。
でも、厳密にはプロパティは「メンバ変数」と呼ぶように「変数」のことなので、
「関数」ではなく誤解だった・・・、ということのようです。)
つまり、
『「関数」と同じ!』、というようなイメージに見えてくるため、
「プロパティ=変数」っていう感じが、「しない」、かもしれません。
が、
「関数名に」
(Z関数の関数名の「z」のように)
「代入ができ」
しかも、
「変数のような感じになってる」・・・、
つまり
「関数名≒変数」
みたいな感じになってる・・・、
ということがイメージできると、
「Property Let 、Property Set 、Property Get 」のプロシージャで作る「自作のプロパティ」は、
極めて「関数的」なんだけれども、
でも
「Z関数」の関数名の「z」のように、
「z」には「まるで変数であるかのように」「代入ができる」、ということが分かれば、
「関数名≒変数」となり、
ひいては
「関数」≒「変数」みたいに捉えらえることもできる・イメージできる・・・・、
ということになり、
「プロパティ=オブジェクト(クラス)が所有する変数」ということからも、
「ギリギリ逸脱してない」、
みたいに(かなり乱暴で無理矢理ですけど)とらえることができ、
クラスモジュールやプロパティの理解・作成が少し楽になります。
※余談
「Property Let 、Property Set 、Property Get 」のプロシージャで作る「自作のプロパティ」は、他の言語やオブジェクト指向プログラミング全般では「ゲッター、セッター(Getter、Setter)」と呼ばれるものに相当するようです。
同時に、
「オブジェクトブラウザ」も読みやすくなります。
(それはどこかで後述します。)
話を戻します。
今回の「z関数」は、「Let」を省略せずに、
Function z(x As Long, y As Long) As Long
Let z = x + y
End Function
と書きました。
なので、
『 ああ、関数名の「z」には、文字系の一般データを代入したんだな・・・』、
ということが分かります。
「Long?なんだこりゃ?」
と思ったとしても、
皆さんはもう、
「Let」と書いてあれば
『 ああ、何らかの変数に、文字系の一般データを代入したんだな・・・』、
と分かる・・・、
と思います。
このことも「超」「大事」です。
(特にデバッグ局面において等々。)
多くの方は、「なんてことない・どうでもいいこと」のように思うかもしれませんが・・・。
そのほか、
「=」についてですが、
この「=」が代入の意味なのか、等しいという意味なのか、
「どっちなんだ!」と
思ったことはありませんか?
(※初心者の方!再度・ごめんなさい!)
ここで、簡単なチェック方法をご紹介します。
「=」のある1行の先頭に「Let」を追記します。
エラーが出なかったり、行の文字が赤く変色したりしなければ、
その「=」は「代入」の意味です。
例えば、
Activesheet.Range("A1").value = "あああああ"
というプログラムコードがあったとき、
Let Activesheet.Range("A1").value = "あああああ"
と、Letを先頭に書いてエラーにならなかったら、
その「=」は代入の意味です。
この場合は、エラーにならないので、「=」は代入の意味です。
If文を1行にしたり、「:」で2行を1行につなげて書いたり、の場合は、
行の先頭ではなくて、意味の切れ目の先頭部分に「Let」を書くことになりますけれど…。
例えば
If ActiveSheet.Range("A1") = "" Then Let ActiveSheet.Range("A1") = "bbbbb"
みたいに。
このとき、Ifの前に「Let」を書くと書いたそばから赤くなって、つまり、エラーになります。
この場合は、
「If ActiveSheet.Range("A1") = "" Then」
の「=」は、
『 代入の意味じゃありませんよ~ 』、
『「イコール」の意味の「=」ですよ~ 』、
ということになります。
「Let」を省略して書かないでいると、「=」がどういう意味の「=」なのか分かりづらいですが、
「Let」を省略せずに書けば、「=」の意味が明確になります。
「省略」を「しない」と、そのように、いろんなことが分かります。
それが、エラーの原因を発見しやすくもしてくれます。
確かにVBAでは、いろんなことが「省略」できます。
確かに便利(?)です。
でも、便利な反面、
でもその省略の「意味」を知っていないと、
「バカになる」「エラーが出る」「確認作業が遅れる」などの弊害もあります。
というか、
「弊害のほうが大きい」
とも思います。
基本、「省略しない」ことで、悪いことが起こることは「1つも」ありません。
逆に、「省略する」と、意味を知らなければ、「悪いことだらけ、エラーだらけ」になります。
Function z(x As Long, y As Long) As Long
Let z = x + y
End Function
には、まだ「省略」があります。
「x As Long」や「 y As Long」の前に
「ByRef」というキーワードが省略されています。
関数の「引数」については、そのコード記述のときに、
「ByRef」か「ByVal」というキーワードのいずれかを書かないといけないのですが、
何も書いてないと
「ByRefを書いた」、
とみなされます。
つまり、
Function z(ByRef x As Long, ByRef y As Long) As Long
Let z = x + y
End Function
と書いたとみなされます。
で、この「ByRef」なんですが、少し間違うとこれまたエラーを誘発します。
で、そのエラーが質の悪いことに、エラーメッセージなどが出ず、
「答えだけが狂う」というエラーになります。
そのようなエラーのことを「論理エラー」と言います。
※そのほかにも、もっと「省略」があるかもです。ご自分でも探してみてください。
また、
Range("A1").Value
と書いたときは、先頭に「ActiveSheet」が省略されています。
つまり、
ActiveSheet.Range("A1").Value
と書いたことと同じ意味になります。
いずれも、ブックの指定やシートの指定をしていないので、
複数のブックやシートを同時に扱う場合は、
注意しないとエラーが頻発したりすることがあります。
もちろん、「論理エラー」もたくさん起こります。
ActiveSheet.Range("A1")
も良くないですね。
これは、「Value」が隠れています。
ActiveSheet.Range("A1").Value
と書くクセにしないと、これも、
思わぬ論理エラー(メッセージの出ない答えが狂うだけのエラー)を引き起こします。
ActiveSheet.Range("A1")という書き方は、
Excel自身が、
「A1セルの値」という意味以外に、
「オブジェクトに間違える」、
というケースもあるからです。
「×××.Range("A1").Value」と「Value」をちゃんと書けば、
その場合は絶対に、
「A1セルの値」という意味に、
Excelは理解してくれます。
で、そう書くクセにしておけば、エラーが出ても、そこは「見直す必要がなくなり」、
ひと手間はぶけます。
以上のように、
VBAの「省略」については、
「どんな省略があって、何がまずいのか?」をちゃんと知っていないと、
自力でエラー解決ができなくなってしまいます。
なので、最初のうちは、「省略」は「悪」だと思って、
面倒くさくても、省略しない書き方を覚えてください。
「省略」は
「全部意味が分かる人に許される行為」であって、
意味も理解できていない初心者がやるべきことではない、
のです。
でも、それを、
今のVBA教育業界は、クズすぎるにもほどがあるのですが、
「推奨」すらしてしまっています。
ExcelVBAにどんな省略があるかは、以下のWebページをご参考にしてください。
https://excel-ubara.com/excelvba4/EXCEL289.html
ただ、このWebページは、「省略=悪」とは書いてなく、
なんなら、
「善」ともとらえられるニュアンスです。
こんなすごい人でも、
「悪ととらえない」ので、
「日本のVBA教育はもう終わってるな・・・」という悲しい気持ちになります。
(※もちろん、こんなすごい人たちは、全部理解しているので、
悪とはとらえない、ということは当然でもありますが…。
でも初心者に対するVBAの「教育」としては、やはり、「悪」です。
「なぜあっちとこっちで言うことが違う?」
「なぜあっちとこっちでコードが違う?」と、
これが、悩み、の原因となります。)
またまた話が逸れましたが、
これまで書いたきましたように、
「Let」を書略しないだけでも、色んなことがわかったりします。
◆それは
◆「市販書籍や動画、Web記事などからは得られない、自分だけの知識」です。
結局は、そういうものを、自分が、欲しいか、欲しくないか、だけなのですが、
でも、「そういうことが今のVBAの教育には隠されて、騙されやすくなっている」ということが
先にわかってないと、「欲しいか、欲しくないか」なんてわかるわけもないので、
まずは、「省略しないで」、VBAコードを書いてみてください。
Activesheet.Range("A1").value = "あああああ"
というプログラムコードがあったとき、
Let Activesheet.Range("A1").value = "あああああ"
とも書ける・・・、
こういうのも、はじめのうちは新鮮ではないかと思います。
◆そういうのがたまっていくと
◆「爆発的な上達」にもひとやくかいます。
そして実際、
プログラムコードの中に
「Let」と
「Set」が
律儀に並ぶと、
なんとなく整然とコードが並んで、単純に見やすくなったり、
「プログラムの間違いの修正」もしやすくなったりします。
デバッグのときも、
「今回のエラーはLetの行は見なくていいや」、とか、そういうこともできるので。
是非、「省略は悪」と思って、色々と省略せずに書いてみてください。
※省略とは少し違いますが、変数を1文字だけで書くのもやめたほうがいいです。
「置換」をしたときに、プログラムがメッチャクチャに置換されて、
地獄を見ることがあります。
省略や1文字変数は、あくまでも「サンプル用」「Q&Aの回答用」なので、
「実務」では、「絶対に真似しないほうが、自分の為になります」。
※省略の悪いところが全部分かった以降は、あえて、省略して書くのはOKだと思います。
「基本も学べてない段階で」、「省略(短く書けること)」が「カッコイイ」などと、
愚かな過ちさえしなければ。
今回は以上です。
==========================================================================
バックナンバー目次とサンプル号
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
----------------------------------------------------------------------