プロシージャとは
同じ処理が複数回出てくる場合を考えてみてください。例えば一箇所に修正が入ったとしても複数あるロジックの全てを修正しなくてはいけません。そのようなプログラムは信頼性も低くなりますし、作業効率も当然悪くなります。このようなときは プロシージャ ( 関数 ) と呼ぶ機能を用い処理単位で独立させて記述する事が出来ます。独立させて記述しておくので何度も同じ記述をする必要がなくコーディング量を減らす事も出来ます。 またバグが見つかった際の改修も、この一箇所のみで済んでしまうためメンテナンスがとても容易になります。

VBScriptでは Subプロシージャ と Functionプロシージャ という2つのプロシージャが用意されていて、戻り値を持たないプロシージャ ( Sub ) と戻り値をもつプロシージャ ( Function ) という感じで分類されます。
Subプロシージャ
Subプロシージャは呼び出し元に値を返さないプロシージャです。 ( 呼び出しもとの値を変更する事も出来ますがそれは後述します ) Subプロシージャは End Sub で囲まれた範囲をプロシージャの範囲として上から順にステートメントを実行していきます。 Exit Sub または End Sub が実行された時点でそのプロシージャから抜けます。
※Exit Subは幾つでも記述できますが、End Subはプロシージャ内で一つしか指定できません。
宣言
Sub プロシージャ名(引数リスト、、)
処理ブロック
End Sub
値リストとはプロシージャに渡される引数が代入される変数で [ 引数 ] と呼ばれます。 呼び出し元からプロシージャに値を渡してそのプロシージャの処理を変化させたい場合などに使用します。 引数はカンマ ( , ) で区切って複数指定することが可能です。
注.) プロシージャに引数が無い場合でも宣言の括弧は必須で()と記述します。
注.) 宣言と呼び出しの引数の数は実行時にチェックされ、一致していないとエラーとなります。
Sub subBold(strMsg)
Response.Write("<b>" & strMsg & "</b>")
End Sub
このSubプロシージャ ( subBold ) は引数で受け取った値を<b>〜</b>タグに挟んで出力します。
呼び出し
SubプロシージャはCall ステートメントで呼び出します。
1. Call プロシージャ名(引数リスト、、)
2. プロシージャ名 引数リスト、、
1では Call ステートメントを使用してSubプロシージャを呼び出しています。この時引数は()で指定する事になります。(引数が無い場合には省略可能です) 2 を見てみましょう、、Callステートメントを使用していませんね。 このような記述をする事も可能で、この時引数の指定は()を省略することが出来ます。
Call subBold("Hello World")
subBold "Hello World"
上の二つはまったく同じ結果を出力します。
引数の受け取り
その他の言語と同じくプロシージャに引数を渡すことが可能です。プロシージャではその引数によって動作を変更したり汎用性を持たせることが出来ます。
[ 呼び出し側 ]
Call printTag ( "Hello World" , "i" )
[ 受け取り例 ]
Sub printTag(strMsg, strTag)
Response.Write("<" & strTag & ">")
Response.Write(strMsg)
Response.Write("</" & strTag & ">")
End Sub
この printTag 関数は、第2引数で受け取った文字をタグとして、第1引数で受け取った値を出力する文字として、以下のように出力します。この関数は1、2引数を変更すれば出力する文字列・タグともに変更することが出来ますので、引数によって汎用的になっているのが分かると思います。
<第2引数> 第1引数 </第2引数>
Functionプロシージャ
Functionプロシージャは呼び出し元に値を返すプロシージャです。 Functionプロシージャは End Function で囲まれた範囲をプロシージャの範囲として上から順にステートメントを実行していきます。 Exit Function または End Function が実行された時点でそのプロシージャから抜けます。
※Exit Functionは幾つでも記述できますが、End Functionはプロシージャ内で一つしか指定できません。
宣言
Function プロシージャ名(引数リスト、、)
処理ブロック
End Function
値リストとはプロシージャに渡される引数が代入される変数で [ 引数 ] と呼ばれます。 呼び出し元からプロシージャに値を渡してそのプロシージャの処理を変化させたい場合などに使用します。 引数はカンマ ( , ) で区切って複数指定することが可能です。
注.) 戻り値の型は VBScriptでは Variantで固定となります。
注.) プロシージャに引数が無い場合でも宣言の括弧は必須で()と記述します。
注.) 宣言と呼び出しの引数の数は実行時にチェックされ、一致していないとエラーとなります。
Function subBold(strMsg)
fncBold = "<b>" & strMsg & "</b>"
End Function
このFunctionプロシージャ(fncBold)は引数で受け取った値を<b>〜</b>タグに挟んで戻り値とします。例えば引数で "Hello World" と言う文字列が渡された場合、関数が呼び出し元に返す戻り値は "<b>Hello World</b>" となります。
C言語などをご存知の方は 「 ん? 」 と思うかもしれません。Cでは関数の結果を戻す場合 "return" ステートメントを使用します。しかし、VisualBasic/VBScript ではこのサンプルのように [ 関数名 = 戻り値 ] と記述します。 また C言語では returnステートメントを実行したときにその関数を終了しますが、VBScriptでは 関数名い戻り値を代入しても終了しないで、Exit/End Function までステートメントを実行します。
呼び出し
では上記で解説した fncBoldプロシージャを呼び出してみます。
1. valRet = fncBold ("Sample")
2. Response.Write(fncBold ("Sample") )
1 では fncBoldプロシージャを実行して、戻り値を 変数 valRet で取得します。
2 は戻り値を変数に取得するのではなく、Response.Writeメソッドの引数として使用しています。当然ですが 1 で取得した valRet を Response.Writeメソッドの引数として指定して実行しても 2 と同などの結果となります。
Call subBold("Hello World")
subBold "Hello World"
上の二つはまったく同じ結果を出力します。
変数のスコープ
ここまで Sub / Function プロシージャの使い方を説明をしてきましたが、今回はプロシージャ内/外で使用する変数のスコープ ( スコープとは可視範囲の意味で、変数を参照できる範囲を表します ) について見てみましょう。これらをしっかり把握していないと、予期していたような結果が得られなかったりする可能性が出てきてしまいます。
まずは下のサンプルをみて、どのような結果となるかを考えて見ましょう。
Dim varData
varData = "JavaScript<br>"
Response.Write(varData) ' T
Call subWriteA
Sub subWriteA()
Dim varData
varData="VBScript<br>"
Response.Write(varData) ' U
Call subWriteB
End Sub
Sub subWriteB()
Response.Write(varData) ' V
End Sub
プロシージャの内/外でそれぞれ varData 変数を出力しています。ここで注意していただきたいのは subWriteA 内で再度 varData を宣言しなおしていることです。結果は以下の通りになります。
JavaScript
VBScript
JavaScript
上記スクリプトでは T→U→V の Writeメソッドという順に実行されます。結果を見ると T ( JavaScript ) 、U ( VBScript ) 、V ( JavaScript) と順番で出力されています。
- まずTが [ JavaScript ] と出力されるのは問題無く予想通りだったと思います。
- 次にUが [ VBScript ] と表示されています。これは subWriteAプロシージャで宣言された varData 変数を出力しているためです。この関数内で宣言を行わなければサブルーチンの外で宣言されている varData の値を上書き/出力します。
- 最後にVが [ JavaScript ] と表示されています。これはsubWriteAプロシージャ内で宣言された変数ではなく、先頭で宣言された変数を参照しているためです。プロシージャ内で宣言された変数はそのプロシージャ内でのみ有効となります。このサンプルでは、呼び出し元が subWriteA であってもプロシージャ内で varDataが宣言されていない限り、スクリプト全体で宣言された varDataを使用します。
| 変数の宣言場所 |
優先度 |
スコープ |
| aspファイル内(プロシージャ外) |
低 |
スクリプト全体 |
| プロシージャ内 |
高 |
プロシージャ内 |
|
複雑な値の受け渡し
プロシージャを使用してスクリプトをプロシージャ単位で記述することが出来ます。ただし若干の不満もあります。例えば Functionプロシージャを使用すれば、呼び出し元に値を返すプロシージャを作成できますが Functionプロシージャの戻り値として返せる値は一つのみです。これでは一つのプロシージャから複数の値を返したいと言う時に使用できません。
ひとつのプロシージャから複数の値を受け取りたい場合、これから説明する引数を使用した方法で実現する事が出来ます。 VBScript には引数の引渡し方法として、 値渡し( ByVal ) と 参照渡し( ByRef ) と言う方法が用意されています。
参照渡し ( デフォルト )
参照渡しとは、変数の参照を呼び出し先へ渡します。つまり「どこどこに格納されている変数」と言うイメージで呼び出し先のプロシージャへデータを提供します。このため、引数として渡されたデータ用に別のアドレスが用意される訳ではなく、同じアドレスにある変数を、呼び出し元、呼び出し先で共有します。
値渡し
値渡しは変数の値のみを呼び出し先へ渡します。値渡しでデータが引数として渡された場合、同じ値をもつ別の変数がコピーして作成されます。このため、呼び出し元、呼び出し先で別個に変数を用意するため、同じ値を持つ変数が2つ存在するイメージになります。
参照渡しによる方法
Dim varData
varData = "JavaScript<br>"
Response.Write(varData) ' T
Call sub_Sample(varData)
Response.Write(varData) ' U
Sub sub_Sample(ByRef lclData)
lclData="VBScript<br>"
End Sub
[ 実行結果 ]
JavaScript
VBScript
一回目の Writeメソッドと 二回目の Writeメソッドで違う文字列を出力しています。ただ出力している変数 varData には先頭で [ JavaScript ] を代入しているだけですので、何故出力される値が変わってしまったのでしょう?
注目して頂きたいのは、一回目と二回目の出力の間で sub_Sampleプロシージャを呼び出していて、引き数で varData を渡している事です。受け取り側の sub_Sampleプロシージャで引き数で受け取った変数に値を代入しています。参照渡しは値ではなく参照を渡すので、 プロシージャ側で変数を変更するとそれが呼び出し側にも反映されて値が変わったと言うわけです。
今回のサンプルではプロシージャの引き数宣言で ByValキーワードを明示的に宣言していますが、VBScriptではデフォルトで参照渡しであるため、このキーワードは省略する事が出来ます。
値渡しによる方法
Dim varData
varData = "JavaScript<br>"
Response.Write(varData) ' T
Call sub_Sample(varData)
Response.Write(varData) ' U
Sub sub_Sample(ByRef lclData)
lclData="VBScript<br>"
End Sub
[ 実行結果 ]
JavaScript
JavaScript
一回目と二回目の出力が同じになっています。前回のサンプルと今回のサンプルの違いはプロシージャの引き数受け渡しの宣言で ByRefキーワードを ByValキーワードへ変更しただけです。これにより値のみの受け渡しとなり、プロシージャ側の変更が呼び出し側に影響を与えなくなったのです。
前述した参照渡しがデフォルトになるので、値渡しを使用するときは明示的に ByValキーワードを記述する必要があります。
プロシージャから複数の値を受け取る
では実際に参照渡しを利用してプロシージャから結果を複数受け取る方法をご紹介します。
Dim varData
Dim varBData
Dim varIData
varData = "VBScript"
Call getTag(varData,varBData,varIData)
Response.Write(varBData)
Response.Write(varIData)
Sub getTag(ByVal strData, ByRef refB, ByRef refI)
refB="<b>" & strData & "</b>"
refI="<i>" & strData & "</i>"
End Sub
[ 実行結果 ]
VBScript
VBScript
このサンプルプロシージャでは一つ目の引き数でタグを付加する文字列を、二、三番目の引き数でタグが付けられた文字列を結果として受け取る用の変数を指定します。このような方法で Sub/Functionプロシージャから複数の値を取得することが出来ました。
|