第9回  「自作関数を作ろう!」



自作関数とは何か?

自作関数とは、自分で作成した関数の事です。
何を当たり前の事を言ってるんだと思われたでしょうが、それだけの事なのです。

関数には、システムが用意してくれているものとそうでないものがあります。
これらは一般的に次のように呼ばれています。

標準関数       (システムが用意しているもの)
ユーザー定義関数  (ユーザーが作成したもの)

つまり、自作関数とは、このユーザー定義関数の事なのです。
「自作関数」とは、私が呼びやすいように勝手に付けた名称です。
納得して頂けましたでしょうか?


関数とは何か?

それでは、「関数」とは何なのでしょうか?
プログラミングの本には必ず書いてある事ですが、簡単にお話しておきましょう。

皆さんは、「Y=2X」という関数を習った事がありませんか?
そう、プログラムの授業ではなく、数学の授業で習っているはずです。
では、この関数の動きをみてみましょう。

X=1」というデータを与えてやれば、「Y=2」という答えを返してくれますね。
同様に、「X=2」とすれば、「Y=4」となります。

このように「データを与えると、それを変換して返してくれるもの」を関数と言います。
プログラムでいうところの関数もこれと同じものなのです。

ところで、この時与えるデータの事を「引数(ひきすう)」又は「パラメータ」と言い、
返されるデータの事を「戻り値」と言います。
以降は、この言葉を使って説明してきますので、覚えてしまって下さい。

最初の例では、引数が「1」、戻り値が「2」となり、
次の例では、引数が「2」、戻り値が「4」となっているわけですね。

ただし、関数によっては、引数や戻り値が無い場合もありますので注意して下さい。
特に、VBでは戻り値の無い関数の事を「サブルーチン」(Sub プロシージャ)と呼んでいます。
ちなみに、C言語では戻り値の有無に関わらず「関数」と呼びます。
また、VBでも戻り値のない関数を作る事はできます

文字列操作の自作関数1

前回、MaferLite.bas ソースプログラム3で自作関数を呼び出していましたね。
そこで使用していた「GetStrL」について解説してみましょう。


StrCtrl.bas ソースプログラム1
Function GetStrL(ByVal Str As String, ByVal StartS As String) As String

  If InStr(Str, StartS) = 0 Then
    GetStrL = ""
    Exit Function
  End If

  Dim StrLength As Integer  '抜き出したい文字の長さ
  StrLength = InStr(Str, StartS) - 1
  GetStrL = Left(Str, StrLength)

End Function


内容を説明していく前に、この関数の目的を確認しておきましょう。
ソースプログラム中コメントにも書いておきましたが、(詳しくは、サンプルプログラムを参照)

この関数は「指定した文字の左側の文字列を取り出す」ために使用します。
そして、第1引数に「元の文字列」、第2引数に「区切りになる文字」を指定します。

例えば、以下の文を実行すると、変数「Moji」の中身は「123」となります。
Moji = GetStrL("123+456" , "+")

では、1行目から見ていきましょう。ここでは関数を宣言しています。
それぞれを細かく見ていくと、

Function 関数である事を指定
GetStrL 関数名
(   )内 引数
As String 戻り値の型

さらに、( )内の引数を見ると、「Str」「StartS」という「String型」の2つが定義されています。
また、戻り値は関数名ですので、「GetStrL」という「String型」の1つになります。
原則として戻り値は1つだけとなります

ここで、引数に「ByVal」というキーワードが付いていますが、今は気にしなくても構いません。
VBで関数を作成するときは、付けた方が良い事が多いのですが、そうでない時もあります。
詳しくは、VBヘルプ「Function ステートメント」の「引数」の欄を参考にして下さい。

それでは、2行目のIf文を見てみましょう。
「InStr」というのは、ある文字列の中から、指定した文字列を検索する標準関数です。

この場合は、第1引数「Str」の中に、第2引数「StartS」が含まれているかを調べます。
そして、もしも指定した文字列が見つからなかった場合は、「0」を戻り値として返します。

つまり、このIf文の中身は、指定した文字列が見つからなかったときの動作を指示しているのです。
具体的には、「GetStrL」の戻り値を「""」(何も無し)にセットし、処理を終了してしまいます。

例えば、こんな指定がされた時ですね。
Moji = GetStrL("123+456" , "*")


一方、文字列が見つかった場合は、End Ifより下の文章が実行されます。
まず、何文字分抜き出すのかを格納するための変数を宣言します。

そして、実際に何文字抜き出すかを求めるのですが、
これには、先ほどの「InStr」関数を使用します。

「Str」に「123+456」が、「StartS」に「+」が格納されている場合を考えてみます。

InStr(Str, StartS) を実行する事で、「123+456」という文字列の中で、
「+」が何文字目にあるかを調べることができます。

この場合は、4文字目に「+」がありますので、「InStr」関数の戻り値は「4」となります。
ただし、ここで抜き出したい文字列は「+」の1つ左の文字まででしたね。
ですから、抜き出したい文字数は、そこから1を引いた「3」という事になります。

続いて、「Left」関数を使用して、「GetStrL」の戻り値をセットしています。
「Left」関数とは、「文字列の左端から指定した文字数分の文字列を返す」標準関数です。

現時点での「Str」の中身は「123+456」、「StrLength」の中身は「3」ですから、
「GetStrL」には、「123+456」の左から3文字分、つまり「123」がセットされるわけです。


どうでしょう、関数の動きはお分かりになりましたでしょうか?
なんか良く分からんぞ!という方は、実際にVBを実行しながら調べてみて下さい。
1行ずつプログラムの動きを追えば、きっと分かるようになるはずです。


自作関数の意義

こういった関数を作成する意味は、第8回にお話しした通りです。
そして、これらは目的毎に標準モジュールに作成しておくと、後々使う時に便利です。

例えば、このように文字列を操作するための関数は「StrCtrl.bas」にまとめておく事にします。
これは「StringControl」つまり、「文字列操作」を略した名前です。
これなら、ここに記述されている関数の目的がすぐに分かりそうですね。
別にこの通りにしなくても構わないのですが、できるだけ分かりやすい名前をつけておきましょう。

余談ですが、仕事でプログラムを作成する事になれば、全てを一人で作成するというのは稀です。
となると、当然何人かでプログラムを見ることになるのですが、
この際に各人がバラバラな名前を使っていると、
他の人が見たときに非常に分かりにくい物になってしまいます。

また、自分で作成したプログラムであっても、時間が経てばかなり忘れてしまっているものです。
この時に、すぐに思い出せるようにしておく方が良いですよね。

さらに、関数の目的や使用方法などをコメントで書いておくと、より分かり易くなるのでおすすめです。


文字列操作の自作関数2

さて、「StrCtrl.bas」には、後2つほど関数を定義していますので、
そちらも簡単に見ていきましょう。


StrCtrl.bas ソースプログラム2
Function GetStrR(ByVal Str As String, ByVal EndS As String) As String

  If InStr(Str, EndS) = 0 Then
    GetStrR = ""
    Exit Function
  End If

  Dim StrLength As Integer  '抜き出したい文字の長さ
  StrLength = Len(Str) - InStr(Str, EndS)
  GetStrR = Right(Str, StrLength)

End Function


例えば、以下の文が実行された場合を考えましょう。
Moji = GetStrR("123+456" , "+")
結果は、「Moji」という変数に「456」が格納されるはずですね?

この事を念頭において、ソースプログラムを読んでいきましょう。

関数の宣言や、If文の所は、GetStrLと全く同じですので省略します。

問題は、抜き出したい文字数を求める所です。
ここで使用している「Len」関数とは、「指定した文字列の文字数を返す」標準関数です。

現在「Str」の中身は「123+456」であり、7文字ですから、
「Len(Str)」の結果は「7」となります。

また、「InStr」の働きは前述した通りですので、「InStr(Str, EndS)」の結果は「4」ですね。
ですから、「StrLength」は「7−4=3(文字)」、つまり「3」となります。

続いて、「Right」関数を使用して、「GetStrR」の戻り値をセットしています。
「Right」関数とは、「文字列の右端から指定した文字数分の文字列を返す」標準関数です。

現時点での「Str」の中身は「123+456」、「StrLength」の中身は「3」ですから、
「GetStrR」には、「123+456」の右から3文字分、つまり「456」がセットされるわけです。


いかがでしょう?
「GetStrL」が分かっていれば、なんて事はありませんでしたよね?

それでは、最後の関数を説明したいと思います。


StrCtrl.bas ソースプログラム3
Public Sub SelText(SelectText As TextBox)
  SelectText.SelStart = 0
  SelectText.SelLength = Len(SelectText)
End Sub


これは、先ほどの2つとは少し毛色の違う関数です。
具体的には、
指定したテキストボックスの中に格納されている文字列を選択状態(反転表示させる)にする
という働きをします。

例えば、以下のように使用します。
SelText txtFileFullpath

何か今までの関数とは違う点に気が付きましたか?
そう、カッコがないんですね。

今回のように、戻り値を持たない関数の場合は、その引数をカッコで括らないのです。
という事は、サブルーチンの呼び出しは、基本的にカッコを使わないという事ですね。

この文が実行されると、「txtFileFullpath」という名前のテキストボックスの中に
表示されている文字列が選択状態(反転表示)になります。

また、カッコを使いたいのであれば、以下のように記述する事も可能です。
Call SelText (txtFileFullpath)
詳しくは、VBヘルプ「Call ステートメント」を参考にして下さい。


それでは1行目から見ていきましょう。
「Public」というのは、そのプロシージャを他のモジュールからも使えるようにするためのキーワードです。
詳しくは、VBヘルプ「Declare ステートメント」を参考にして下さい。

同じく1行目に「Sub」というキーワードがありますが、
これは「サブルーチン」である事を定義するためのものです。

冒頭でお話しましたが、戻り値の無い関数は「サブルーチン」でしたね。
そこで、「Function」の代わりに「Sub」としているわけです。

ただし、ここで「Function」と書いても特に問題はおきません。
ですから、使い分けるのが面倒な場合は、いちいち「Sub」を使わなくても構いません。
今回は、「Sub」(プロシージャ)ステートメントを紹介するために使用したまでの事です。

「SelText」というのが関数(サブルーチン)の名前です。
「SelectText」は引数で、その型は「TextBox」型です。

これは普通の変数の型とは異なり、オブジェクトを指定しているのですが、
テキストボックスコントロールのオブジェクト名を、引数として指定しているだけの事で、
あまり難しく考えなくても構いません。

2行目では、選択される文字の開始位置を、文字列の先頭にセットし、
3行目では、選択範囲の文字数を、テキストボックスに表示されている文字数と同じにセットしています。

詳しくは、VBヘルプ「SelStart プロパティ」の「選択されているテキストの処理」を参考にして下さい。
使用方法が、ほぼそのまま載っています。


文字列操作はこれだけじゃないっ!

ここまでで3つの文字列操作関数を作成できたわけですが、
他にも考えられる文字列操作はたくさんあります。

「ある文字列から指定した文字を取り除く」、「ファイルのフルパス名からファイル名を抜き出す」
といった関数もあれば便利そうですね。

他にも、文字列操作に関しては、プログラムを作成しているうちに
どんどん必要なものが出てくると思います。
そういった関数が標準関数に無い場合は、自分の手で作り上げてみてはいかがでしょうか?

この他にも、「指定した文字で囲まれた文字列を取り出す」ために
「GetStrM」という関数も作っていたのですが、サンプルプログラムでは削除しておきました。

使用例は以下の通りです。
Moji = GetStrM("123+456=579" , "+" , "=")

この文を実行すると、「Moji」という変数に「456」が格納されます。
できれば、皆さんの手で「GetStrM」関数を完成させてみて下さい。


さて、今回はここまでです。
次回は、ファイルを実際に書き換えている自作関数をみていきましょう。



前に戻る     次に進む

講座の初めに戻る