ロゴ(青) Excel/VBA Tips ロゴ(緑)

Tips01: 『引数』ってな〜に? どう使うの?(子供のお使い)

ここに載せたのは、私がエクセルファンクラブで回答の際に考えた例え話です。
      http://www.keep-on.com/excelyou/2000lng5/200010/00100128.txt
他に、モーグ(Excel/VBA)ExcelFactory/犬でもわかるExcelVBA講座/用語を覚える
紹介しました。

UserForm関連話 : 「ByVal なのに [ Cancel = True ] が有効なのは何故?」  ( 2009/1/12 追記 )

-------------------------------------------------------------------------
『引数の意味がわかりません。』
      「引数」っていう言葉の意味がわかりません。
    あまりに初心者的質問なので、どこにも書いていない(涙)
      なんとなくはわかってきたのですが、正確な言葉でどなたからか
    わかりやすくお教えいただければと思います。
    いつもその言葉が出てくると悩んじゃうんです。
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
こんにちは。

『引数』は【関数】や【サブルーチン】を利用する時に、
    関数やサブルーチンに対して
      ・動作条件を指定する
      ・処理結果を受け取る
という為に使うものです。機能的にはこれだけです。

例え話で説明してみますと。
      サブルーチン:八百屋へお使いを頼んだ子供
      処理内容    :お買い物
      引数1        :買い物リスト
      引数2        :サイフ
      引数3        :買い物かご

  単に「八百屋へ行ってきて」では子供も何を買ってくればいいのか判りませんよね。
そこで「買い物リスト」に”大根1本”と書いて持たせてやります。
買い物にはお金が要りますから「サイフ」に”千円”を入れて持たせてやります。
買った物を裸で持ってくるのはなんですから、「買い物かご」も持たせましょう。

  『さあ、いってらっしゃい』と子供を送り出すのが【サブルーチンの実行】に相当します。

  『サブルーチン:子供のお使い』は八百屋さんに着くと、
      ・引数『買い物リスト』に書いてある”大根1本”と引数『サイフ』に入っている”千円”で
        買い物をします。
      ・八百屋さんは、大根とお釣りをくれたので、大根を引数『買い物かご』に入れ、
        お釣りを引数『サイフ』に戻します

  『サブルーチン:子供のお使い』は家に帰ってくると、
      ・引数『買い物かご』から大根を、
      ・引数『サイフ』からお釣りを
お母さんに渡します。

  このように、引数には、使い方によって
      ・値を渡すだけ  ‥‥‥‥‥‥  買い物リスト
      ・値を受け取るだけ  ‥‥‥‥  買い物かご
      ・値を渡す&値を受け取る‥‥  サイフ
の3種類があります(補足説明 参照)。

  また引数には【属性】があります。
      「買い物リスト」の属性は”大根1本”などの【八百屋さんで売っている物】
      「サイフ」の属性は【お金】
      「買い物かご」の属性は【買った物を入れる】

  「買い物リスト」に”ビール”と書いたり、「サイフ」に”葉っぱ”を入れて、子供を八百屋さんに
送り出しても買い物は出来ませんよね。

  引数には、その属性に合った値を設定しなければ、正しく動作しません。
『エラーが有ります』というメッセージを表示してExcelに怒られてしまいます。

  子供が八百屋さんに怒られて、「買い物できないよ。どうする?」と、お母さんに電話するのに
相当します。

こんなところで、どうでしょうか? (^_^)/~~~ 

補足説明) 2003/5/1 追記
    「値を渡すだけ」の引数は、通常【値渡し】方式として定義します(キーワードは[ ByVal ] )。
    「値を受け取るだけ」と「値を渡す&値を受け取る」の引数は【参照渡し】方式として定義
    します(キーワードは[ ByRef ] )。

    【値渡し】の特徴
   (1) 引数定義には、[ ByVal 」キーワードを付ける(VB/VBAの場合)。
   (2) 関数/サブルーチン内で、引数の内容を変更しても、呼び出した側で定義してある、その引数に指定した変数の内容は変わらない。
(補) ByVal なのに内容を変更できる場合もあります。
   (3) 呼び出し側で、引数に『定数』を指定する事を想定している場合は、通常その引数は【値渡し】で定義する。

    【参照渡し】の特徴
   (1) 引数定義には、[ ByRef ]キーワードを付けるか、もしくは[ ByRef / ByVal ]どちらも記述せずに省略する(VB/VBAの場合)。
   (2) 関数/サブルーチン内で、引数の内容を変更すると、呼び出した側で定義してある、その引数に指定した変数の内容も変更される。
   (3) 通常「値を受け取る」為に使うので、呼び出し側に記述する引数には、呼び出し側で定義した『変数』を指定する(「値を渡すだけ」の場合に[ ByRef ]で定義しても全く構わないので、その際には『定数』を指定しても問題ないが、関数/サブルーチン内で引数の内容を変更する場合に『定数』を指定した際の「動作の保証」は一切無い)。
   (4) オブジェクト変数を引数とする場合は、通常[ ByRef ]にて定義する。
   (5) 関数(Function )において、2つ以上の値を呼び元へ返したい場合に[ ByRef ]引数を利用する(1つ目は関数の戻り値として返し、2つ目以降は引数の内容を書き換える事で値を返す)。
    例: 処理の際のエラー有無を関数の戻り値として[ True/False ]で返し、
          処理の結果を引数で返す。

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
[ この場所へのリンク ]
ByVal なのに [ Cancel = True ] が有効なのは何故?  ( 2009/1/12 追記 )

    (注) 以下の解説は、UserFormのマクロを作成できるレベル以上の人が対象です。VBA初心者で未だ
        「引数って何?」という段階の人には難しいです。この部分は、このように書けばそれで良いんだと
        いう風に覚えておけば充分です。


UserFormのTextBoxで、入力エラーの際にフォーカスを留める為には、以下のコードが
用いられますね。
 
 Private Sub TextBox1_Exit(ByVal Cancel As MSForms.ReturnBoolean)
   If Not IsNumeric(TextBox1.Value) Then
     Cancel = True
     Exit Sub
   End If
 End Sub

1行目のExit プロシジャーの引数定義部分はVBEの自動生成で作られたものです。ここで、
[ Cancel ] 引数は【ByVal 】 で定義されていますが、上記のコードを動かせば『Cancel 引数
の True 値への変更』が正しく実行されてフォーカスが留まります。

前述の解説で「ByValで定義した引数を変更しても呼び元にある変数の実体へは反映されない」
と説明しました。しかし、上記のマクロでは『True値への変更』が呼び元(Excel/VBA)へ伝わって、
フォーカスを留める動作をしています。これでは、ByVal の動きに反しますね。何故、値の変更が
有効になるのでしょうか?

この理由を理解するには、先ず[ Cancel ]がどのように定義されているかが重要です。コードを見
れば、
      MsForms.ReturnBoolean
という属性になっています。普段、変数の定義で使っている「Integer , String , Boolean etc. 」とは
違いますね。これの正体は、オブジェクトブラウザというものを使って調べることが出来ます。

ReturnBoolean は Class となっていますね。つまり、[ Cancel ] 引数はクラスオブジェクトです。
クラスオブジェクトを ByVal で引数定義すると、クラスオブジェクトの実体を指し示すアドレスが、
変数の値として「値渡し」で渡されます。サブルーチン側では、そのアドレスを通してクラスオブ
ジェクトの実体にアクセスできます。しかし、「アドレス値」を変更してクラスオブジェクトを壊したり、
他のオブジェクトへアクセスする事はできません。この部分で、ちゃんとByValの動作を行なって
いる訳です。

ひとつの例えで説明すると、セルというオブジェクトを扱うサブルーチンを考えて
      (1) セルの「オブジェクトそのもの」を渡す( ByRef )
      (2) セルが持つ「値」だけ渡す( ByVal )
      (3) セルのアドレスである「A1」という情報だけ渡す( ByVal )
(1)では、セルそのものを貰ってますから、セルの値でも書式でも如何様にも操作できます。
(2)では、値を貰っただけですから、セルそのものには一切触れません。
(3)では、Range(引数) という使い方をする事で、セルそのものを如何様にも操作できますが、
貰った引数の内容("A1"というセルアドレス文字)を変えただけでは、セル本体には何ら影響
ありません。オブジェクトをByVal で渡すというのは、(3)のような使われ方を意味します。

更に、ReturnBoolean クラスのメンバを見てみると、Value プロパティに青マークが付いており、
「既定メンバ」と説明されていますね。既定メンバとは、クラスオブジェクト名だけで、プロパティが
記載されていない場合に採られる暗黙のプロパティです。つまり、上記のコードでは
    Cancel = True
としか書いていませんが、本来は
    Cancel.Value = True
という書き方が正式です。そして、Value プロパティが普通のBoolean 型であり、Cancel 引数で
渡されたオブジェクトのアドレスを通してアクセス(変更)する事が可能になっている訳です。





  Home    Back Page    Next Page

ロゴ(ゴールド)   ロゴ(ゴールド)

角田 桂一 Mail:addinbox@h4.dion.ne.jp CopyRight(C) 2001 Allrights Reserved.