パソコン活用研究5番街(Visual Basic、Excel(VBA)、BASIC プログラミング研究)

         プロシージャ(Sub, Function)とデータの受け渡し

------------------------------------------------------------------------------------
VBにしろ、VBAにしろ、コードはプロシージャに記述することになります。これはVB,VBAが
旧BASIC(F-BASICやN88Basicなど)と大きく違う(進化した)点です。今回はプローシージャに
ついて基本的なところをまとめてみました。
------------------------------------------------------------------------------------

(1) VB,VBAのプロシージャ
VB,VBAには以下の2つのプロシージャがあります。

T) Sub プロシージャ
  Sub
  〜
  End Sub

U) Function プロシージャ
  Function
  〜
  End Function


(2) プロシージャと旧BASICのサブルーチン(Gosub)
変数のスコープのところで、変数には、ローカル変数、モジュール変数、グロ-バル変数があると、説明
しました。全ての変数をグローバル変数としてしまえば、Subプロシージャの使い方も、旧BASICの
Gosub ......... Return によるサブルーチンにかなり近い感じになります。(厳密には違いますが)

例えば 変数X (=10)を2倍にして返すプログラムを考えます。
旧BASIC VB, VBA


10 X=10      
20 gosub 50
30 end

40 'sub routin
50 X=X*2
60 return
public X as integer

Sub main()
X=10
twice
End Sub

Sub twice()
X=X*2
End Sub

まあ、なんとなく似た感じのコーディングですね。
でも、なんでもかんでもグローバル変数にしてしまっては、進化したVB, VBAのよさをスポイルしてしまいます。
ではVB, VBAの進化にふさわしい使い方でコーディングしてみましょう。


(3) Subプロシージャ (参照渡し)
先に書いたように、プロシージャを呼ぶには、単にプローシジャ名を書けばO.K.です。

今回は、データも呼び出すプロシジャに渡します。データも渡す場合は
プロシージャ名 データ  (ここでは、 twice x)
と記述します。呼び出し側のxを実引数と言います。

呼び出される方は
Sub プロシージャ名(変数 as 変数型)
と記述します。
ここでは Sub twice(a as integer) です。呼ばれるプロシ−ジャ側のaを仮引数と言います。


それでは、上のプログラムをほんの少し拡張して、VBでテキストボックスに入力された整数を2倍にする
プログラムを作ってみます。フォームの構成は、テキストボックス1つに、コマンドボタン1つです。
コマンドボタンを押すと(Sub Command1_Click)、プロシージャtwiceを呼び、Sub twice()プロシージャで
渡された引数2倍にするという簡単なプログラムです。


'
最初はFORM等のプロパティ         

VERSION 4.00
Begin VB.Form Form1 
   Caption         =   "Form1"
   ClientHeight    =   1635
   ClientLeft      =   1140
   ClientTop       =   1515
   ClientWidth     =   3345
   Height          =   2040
   Left            =   1080
   LinkTopic       =   "Form1"
   ScaleHeight     =   1635
   ScaleWidth      =   3345
   Top             =   1170
   Width           =   3465
   Begin VB.CommandButton Command1 
      Caption         =   "twise"
      Height          =   375
      Left            =   1800
      TabIndex        =   1
      Top             =   120
      Width           =   1335
   End
   Begin VB.TextBox Text1 
      Height          =   375
      Left            =   1920
      TabIndex        =   0
      Top             =   840
      Width           =   1215
   End
   Begin VB.Label Label1 
      Caption         =   "値"
      Height          =   255
      Left            =   1920
      TabIndex        =   2
      Top             =   600
      Width           =   855
   End
End
Attribute VB_Name = "Form1"
Attribute VB_Creatable = False
Attribute VB_Exposed = False


' ここからがコードの本体
'


Sub twice(a As Integer)
a = a * 2
print"a: ";a
End Sub


Private Sub Command1_Click()
Dim x As Integer
x = Val(Text1.Text)
twice x
Print "結果"; x
End Sub
FORM上にtwiceプロシージャのローカル変数aと、twice呼出し後のxを出力させています。
実行結果は以下の通り。
5を入力した結果、xは10になりました。
プロシージャtwiceでは変数aに5を受けて、2倍にしています。
aは当然10になりますが、その結果、xも10になりました。どうしてでしょうか。
実は、これが参照渡しといわれる、データの受け渡しの秘密の部分なのです。
参照渡し、とは、データの格納されている場所(アドレス)を渡す方法です。

少し具体的に言えば、プロシージャtwiceが呼び出された時、変数xの格納されているアドレス
が変数aの参照すべきアドレスとしてtwiceに渡されたのです。
すなわち aの参照するアドレス = xの参照するアドレス、となったわけです。
したがって、aの値を変更する = xの値を変更する、というわけです。

xもaもともにローカル変数です。このように参照渡しを使えば、グローバル変数を使わなくても、
プローシージャ間でデータの受け渡しができるわけです。
少し、VB,VBAの進化した部分を使ったプログラムとなりました。
ただし、この例のように、aの変更がxの変更につながってしまいますので、変数の独立性という
点はやや難ありです。参照渡しを使う場合の注意点です。


(4) Subプロシージャ (値渡し)
今度は、値渡しをみてみます。
値渡し、とは、データのコピーをプロシージャに渡す方法です。

値渡しでは、プロシージャの呼び出しは、参照渡しと同じです。
プロシージャ名 データ
と記述します。

呼び出されるプロシージャの方は、変数名の前にByvalをつけます。(”値によって”の意)
Sub プロシージャ名(Byval 変数 as 変数型)

とりあえず、twiseが値渡しになっている以外、上と同じVBプログラム(Byvalがついて、
いるだけ)をみてみましょう
プロパティの部分は省略します


Sub twice(ByVal a As Integer)
a = a * 2
print"a: ";a
End Sub


Private Sub Command1_Click()
Dim x As Integer
x = Val(Text1.Text)
twice x
Print "結果"; x
End Sub

実行結果です

5を入力して、twiceを呼びました
aは10になりましたが(当然です)、xは5のままです。aの変更の結果が、xに反映されていません。
これは、値渡しが参照渡しと違う方法で、データを受け渡ししているためです。

冒頭で、値渡しは、データのコピーを渡す、と書きましたが、下図を見てください。

xのダータ格納場所   5
   
   
   
aのデータ格納場所   5  <−−−5がコピーされた

twiceが呼び出されると、xの値である5がコピーされて、aのデータ格納場所に5が置かれます。
プロシージャtwiceでaが2倍されると、次のようにaは10になります。しかし、aとxの格納場所は互いに
別々で独立していますので、xには反映されません

xのダータ格納場所   5
   
   
   
aのデータ格納場所   10 

と、これが値渡しです。この方法では、変数の独立性がきわめて高くなります。
なお、VB,VBAではデフォルトでは参照渡しとなりますが、C言語では値渡しがデフォルトです。

(5) Functionプロシジャ
Functionプロシージャは、旧BASIC流にいうと関数に近い(ユーザー定義関数というのがあった)もの
と言ってもいいでしょう。
Subプロシージャとの違いは、戻り値を持つということです。

Functionプロシージャの呼び出しは
変数 = プロシージャ名(データ)
となります。
Functionプロシージャからの戻り値があるので、その戻り値を変数に代入します。
渡すデータは (   ) で囲みます

呼び出される方は
Function プロシージャ名(変数 as 変数型) as 変数型
と記述します。
2番めの変数型はFunctionプロシージャの戻り値の型です。

それでは、上と同じく、2倍にして返すプログラムをFunctionで作ってみます。
プロパティ部分は省略します

Function twice(a As Integer) As Integer
twice = a * 2
End Function


Private Sub Command1_Click()
Dim x As Integer, result As Integer
x= Val(Text1.Text)
result = twice(x)
Print "結果"; result
End Sub


result = twice(x) でFunction twiceに変数xを渡し、戻り値をresultに受けています。
なお、Functionプロシージャでの戻り値は、プロシージャ名と同じ名前の変数に代入します。
ここではtwiseです。
Functionプロシージャでも、値渡し、参照渡しの問題はSubプロシージャと同じことです。

(6) EXCELにおけるFunctionプローシジャの特例
EXCELではFunctionプロシージャで引数を持たないばあい、セルの数式として使えるという、特例があり
ます。
セルA1の値を2倍にするFunctionプロシージャ

[Moduleシート]
Function twice()
twice=cells(1,1)*2
End Sub


ワークシートのセルB1にプロシージャ名を式として書いて、リターンキーを押します

  A B C
1 10 =twice()  
2              
3      

すると,下記のとおりになります

  A B C
1 10 20      
2              
3      



TopPage > Visual BasIc&Excel活用研究目次