第7講 ファンクションプロシージャの学習
第1話 ファンクションプロシージャの実例
ファンクションプロシージャの実例
Private Sub CommandButton1_Click()
  CommandButton2_Click '社員CommandButton2_Clickに仕事を依頼
  
Dim a As Integer 'ローカル変数を用意
  a = 3 '箱aに3を代入
  Cells(3, 2) = "a=" 'B3にa=と表示
  Cells(3, 3) = a '箱の中身を表示
  Cells(4, 2) = "a=" 'B4にa=と表示
  Cells(4, 3) = f(
a) 'fにaを2倍してもらってからaの中身を表示
End Sub
Function f(a As Integer)
  f = 2 * a 'aを2倍してCommandButton1_Clickに報告(返す)
End Function
Private Sub CommandButton2_Click()
  Rows("3:2000").Select
  Selection.ClearContents
  Cells(1, 1).Select
End Sub
参考ダウンロード添付ファイル
実行結果
051

Private Sub CommandButton1_Click()
  CommandButton2_Click '社員CommandButton2_Clickに仕事を依頼
  Dim a(0) As Integer 'ローカル配列を用意したが、要素数が1個なので変数を用意したのと実質は同じ
  a(0) = 1 '箱a(0)に1を代入
  Cells(3, 2) = "a(0)=" 'B3にa(0)=と表示
  Cells(3, 3) = a(0) '箱の中身を表示
  Call f(a) '社員fに仕事を依頼 引数で送っているのはa(0)の中身の1ではなく、金庫aの隠し場所の住所
  Cells(4, 2) = "a(0)=" 'B4にa(0)=と表示
  Cells(4, 3) = a(0) '箱の中身を表示
End Sub
Sub f(x(0) As Integer)
  x(0) = 2 '箱x(0)に2を代入
End Sub
Private Sub CommandButton2_Click()
  Rows("3:2000").Select
  Selection.ClearContents
  Cells(1, 1).Select
End Sub
に似ていますが、かなり事態は異なっています。
用意したものは
  Dim a As Integer 'ローカル変数を用意
あくまでプロシージャCommandButton1_Click内で有効なローカル変数です。
ローカル
配列の場合には箱a(0)の在処を教えることによって、
箱の中をいじってもらっていて、
一見箱を渡したのと同じ結果を導いていますが、
箱そのものは絶対に渡せないのです。
社長室の箱(金庫)だけでなく、
それぞれの社員にも仕事部屋が用意されていて、
その部屋の中に金庫が隠してあり、
他の社員には金庫の中身をいじれないようなっています。
仕事を依頼した社員に一時的に自分の部屋に来てもらい、
自分の隠し金庫をいじってもらったと考えて下さい。
一時的に来てもらうというのは、仕事を依頼した社員にも仕事部屋があるからです。
ですから、箱(変数)そのものを渡すことはできないのです。
配列の場合には箱a(0)の住所を渡していますが、
住所は16進数で表示される値です。
記憶装置の番地を示すものが、住所なのですから。
箱そのものを渡したのではなく、
箱の住所=値を渡したのです。
今回の
  Cells(4, 3) = f(a) 'fに2倍してもらってからaの中身を表示
も箱aを渡したのではなく、箱aの中に入っている値3を渡したのです。
どんな場合にも箱(変数)そのものは渡すことが出来ず、
渡せるのは値のみです。
C言語が魅力的なのは変数の住所を扱うポインタという変数が用意されていることです。
C言語でも箱の住所を他の社員に教えることによって、
箱の中身を変えてもらうことが出来るだけでして、
決して箱を渡したわけではありません。
VBやVBAにはポインタがありませんので、
第6講第8話で変数を添え字付きの変数=配列にすることによって、
箱の住所を渡しましたが、
配列以外ではVBやVBAでは箱の住所を教える方法はないのです。
そうすると、VBAはC言語より劣るかと申しますと、
最近のプログラム言語はポインタを使わない方向に進んでいると思います。
これは、やはり変数はこの変数を用意した社員のみがいじるべきで、
変数を他の社員にいじらせるのは、危険です。
スパゲティプログラムまで行かないにしても、
自分が用意した変数は自分専用のもので、
他の社員はいじれないようにした方が、
構造化プログラミングの思想から言ってよいことになります。
尚、他の社員から箱の中身がいじれないことすなわち見えないことを抽象化と呼び、
構造化プログラミングという言い方がされなくりつつある現状があります。
ですが、抽象化と言う用語に私は反対です。
それならばブラックボックス化とか、、
「蓋をして中身を見られないようにする」とか、
遮蔽(しゃへい)化という言い方の方が適切だと思います。
なぜ、構造化プログラミングと言う素晴らしい用語があるのに、
抽象化などと初心者を混乱させる呼び方をするのか、本当に心の底から疑問です。
情報技術(IT)界の問題は、カタカナ乱発と漢字にするときに適切でないものを使っていることであると思っています。
値渡し(箱の中の値を渡すこと)を参照渡しと呼びますが、
参照渡しなら中身渡しの方が適切です。
参照とは箱の中身をコピーして使うことでしたね。
ですから、
  Cells(4, 3) = f(a)
は中身渡しです。箱aの中に入っている値3を渡しているのです。
そして、受け取る側は
Function f(a As Integer)
私書箱の名前をaにしただけです。
CommandButton1_Clickの用意した箱の名前と同じですが、
その箱とは別の箱です。
ですから、例えば、
Function f(x As Integer)
  f = 2 * x 'xを2倍してCommandButton1_Clickに報告(返す)
End Function
としてもよいのだという話はすでにしてありましたね。
自分の私書箱をなんと呼ぼうが自由だからです。
プロシージャ内でその名前で統一してあれば。


値を返すには、VBの場合には、
  f = 2 * a 'aを2倍してCommandButton1_Clickに報告(返す)
ファンクションプロシージャ名に返す値を代入することによって返します。
C言語では
  return(2 * a);
と書き、 2 * a を返すことが一目瞭然ですが、
別に好みの問題であり、この点ついて
C言語の方が優れているとは言えないと思います。
ファンクションプロシージャ名に返す値を代入することに違和感を持つ必要はないのです。
C言語でも値を返す関数は、関数自身が値を持っていると考え、
その値が整数型である場合には、その関数を整数型関数とC言語では考えます。
もちろん文字を返す関数の場合には、文字型関数であると考え、
実数を返す場合には、実数型関数と考えるのです。
値を持っていると考えるなら、
VBやVBA方式
  f = 2 * a
も当を得ていると思います。
ファンクションプロシージャの持っている値が返されると考えればすっきりします。
ファンクションプロシージャの値は引数が決まれば決まります。
ファンクションプロシージャはまさに関数です。
y=f(x)
はxが決まればyが決まりましたね。
そういうものを関数というのです。
正確には、xを決めるとyがただ1つに決まるですが。
VBAや他のプログラム言語でも、
報告する社員は常に1つの値だけを返します。
z=f(x、y)
のように引数が複数であっても返される値は常に1つです。
入力が同じであれば、
出てくる答えも常に同じであることが、
関数の重要な特徴です。
ジュースの販売機でもお金を投入してボタンを押したときに出てくるジュースは、
1種類に決まっています。
毎回気まぐれで異なるジュースが出てくることはありません。
1つの値し返せないとすると、
添え字付き変数である配列の複数の値を返す方法はないのでしょうか。
複数の値とはx(0)=5,x(1)=8,x(2)=11,・・・のように配列は複数の変数ですから、
収納している値も複数ですね。
1つの値しか返せないファンクションプロシージャでは不可能であるように見えますが、・・・
実はありますよ。
答えは?!・・・
後の講で示します。

ところで構造化プログラミングとは、
独立した部品をせいぜい数カ所で結合させるプログラミングであると申し上げましたが、
Private Sub CommandButton1_Click()
  CommandButton2_Click '社員CommandButton2_Clickに仕事を依頼
  Dim a As Integer 'ローカル変数を用意
  a = 3 '箱aに3を代入
  Cells(3, 2) = "a=" 'B3にa=と表示
  Cells(3, 3) = a '箱の中身を表示
  Cells(4, 2) = "a=" 'B4にa=と表示
  Cells(4, 3) = f(a) 'fにaを2倍してもらってからaの中身を表示
End Sub
Function f(a As Integer)
  f = 2 * a 'aを2倍してCommandButton1_Clickに報告(返す)
End Function
の結合部分は何カ所ですか。






第6講第8話へ 第2話へ

トップへ