【2/17】今年は「濃厚」技術トーク!@ITメールセミナー スラッシュドット    はてなブックマーク  Yahoo!ブックマークに登録  印刷
   
基礎解説
チェック式 WSH入門 第7回

3.Subプロシージャと引数(2)

Microsoft MVP
Visual Developer - Scripting
牟田口 大介
2006/12/07
Page1 Page2 Page3

複数の引数を取るSubプロシージャ

 引数は1つではなく複数取ることもできる。第3回で登場したBMI(Body Mass Index、肥満度の判定に用いる指数)を求めるスクリプトをSubプロシージャ化したものが次のコードである。

Option Explicit

Call ShowBMI(CDbl(1.75), CDbl(60)) '身長175cm、体重60kg
Call ShowBMI(0, 0) '無効なデータ
Call ShowBMI(CDbl(1.80), CDbl(91)) '身長180cm、体重91kg

'*********************************************************
'用途: 与えられた身長と体重からBMIを求め、表示する。
'受け取る値: dblHeight: 身長(m単位)(Double)
'            dblWeight: 体重(kg単位)(Double)
'戻り値: なし
'*********************************************************
Sub ShowBMI(dblHeight, dblWeight)
        '引数のチェック
        If Not(TypeName(dblHeight) = "Double" And _
           TypeName(dblWeight) = "Double") Or _
           dblHeight = 0 Then
                MsgBox "引数が正しくありません"
                Exit Sub 'Subプロシージャを抜ける
        End If

        'BMIを求める(小数点以下2位で丸める)
        Dim dblBMI
        dblBMI = Round(dblWeight / (dblHeight * dblHeight) ,2)

        Dim strMessage
        'BMIから肥満度を判定する
        If dblBMI >= 25 Then
                strMessage = "あなたは、肥満です。"
        ElseIf dblBMI <= 18 Then
                strMessage = "あなたは、やせです。"
        Else
                strMessage = "あなたは、標準です。"
        End If

        MsgBox strMessage & vbCrLf & _
        "身長=" & dblHeight & "m、体重=" & dblWeight & "kg、BMI=" & dblBMI
End Sub

 このスクリプトを実行すると、次のような3つのメッセージ・ボックスが連続して表示される。

SubプロシージャShowBMIを実行した例
BMIの値を計算する部分をSubプロシージャ化し、それを3回呼び出している。

 ここではdblHeightに身長、dblWeightに体重の値を与えて、SubプロシージャShowBMIを3回呼び出している。ここで注意が必要なのは、実引数の数と仮引数の数は一致している必要がある点である。

 SubプロシージャShowBMIの前半部分では、与えられた引数が正しい値かどうかを判断している。dblHeight およびdblWeight がDouble型でないか、dblHeight が0(コード中にdblHeightで割るところがあるので、0で割るとエラーになる)だと、警告メッセージを表示した後Exitステートメントを用いSubプロシージャを抜ける。このExitステートメントはFor〜Nextステートメントの解説で登場したものと同様であり、Exitした後のコードは実行されず、呼び出し元の次の行に制御を移す。この場合、BMIを計算する部分は実行されないことになる。

 残りの部分は実際にBMIを計算し、Ifステートメントで肥満・やせ・標準を判定しているのだが特に説明は必要ないだろう。

カレンダーを出力するSubプロシージャ

 ここでSubプロシージャのおさらいをするための例題を1つ取り上げる。指定した日の含まれる月のカレンダーを出力するスクリプトを考えてみよう。ここでは、カレンダーを表示する部分をSubプロシージャ化し(ShowCalendarという名前を付ける)、引数に日付を受け取るようにしたい。

マーカーで隠れたところを、1つずつクリックしてチェックしてみよう。 マーカーで隠れたところを、1つずつクリックしてチェックしてみよう。
Option Explicit

Call ShowCalendar(Date) '今月のカレンダーを表示する。
'2007年12月のカレンダーを表示する。

'*********************************************************
'用途: 与えられた日付が含まれる月のカレンダーを作成し表示する。
'受け取る値: dtmDate: 日付(Date)
'戻り値: なし
'*********************************************************
    Dim dtm1stDate, intLastDay, intOffset, strCalendar

    'もし与えられた引数がDate型でなければSubプロシージャを終了する


    '月の最初の日付を取得
    dtm1stDate = DateSerial(Year(dtmDate), Month(dtmDate), 1)
    '月の最後の日を取得(次月の最初の日の1日前)
    intLastDay = Day(DateAdd("d", -1, DateAdd("m", 1, dtm1stDate)))
    '月の最初の日の曜日=1週目のオフセットを取得
    intOffset = WeekDay(dtm1stDate, vbSunday)
    'カレンダーのヘッダ部分(年/月)を変数に代入
    strCalendar = Year(dtmDate) & "/" & Month(dtmDate) & vbCrLf & vbCrLf
    'カレンダーの曜日名を変数に代入
    strCalendar = strCalendar & _
    Join(Split("日,月,火,水,木,金,土", ","), vbTab) & vbCrLf & vbCrLf

    Dim intCounterDay, intCounterWeek, intTempDay

    intTempDay = 1 '1日ごとに加算されるカウンタ

    '週ごとに回されるカウンタ
    For intCounterWeek = 1 To 6
        '日〜土回されるカウンタ
        For intCounterDay = 1 To 7
            'もし、最初の週でオフセットより先の日、
            'もしくはほかの週の場合、
            'かつintTempDayが最後の日まで行ってなければ
            If ((intCounterWeek = 1 And _
            intOffset <= intCounterDay) Or _
            intCounterWeek > 1) And _
            intTempDay <= intLastDay Then
                'カウンタの日とタブを変数に代入
                strCalendar = strCalendar & intTempDay & vbTab
                'カウンタを1つ増やす(インクリメントする)
                intTempDay = intTempDay + 1
            'そうでない場合は
            Else
                'タブだけを代入する
                strCalendar = strCalendar & vbTab
            End If
            If intCounterDay = 7 Then
                '週の最後は、文字列の最後のTabが余計なので削る
                strCalendar = Left(strCalendar, Len(strCalendar) - 1)
            End If
        Next
        '週ごとに改行コードを入れる
        strCalendar = strCalendar & vbCrLf & vbCrLf
    Next

    '変数の中身を表示
    MsgBox strCalendar

 このスクリプトを実行すると、例えば次のようなメッセージ・ボックスが表示される。

カレンダー表示スクリプトの実行例
指定した日が含まれる月のカレンダーを出力する部分をSubプロシージャ化している。

 少し長いスクリプトだが、Subプロシージャの宣言と使い方についてこれで理解していただけると思う。また、このような長いSubプロシージャを、スクリプト・レベルから何回も呼び出すことができるので効率的であることもお分かりいただけると思う。

 余裕があれば、このスクリプトが実際にどういう動きをしているのか、追ってみてもらいたい。これまでの知識を総動員すれば可能であるはずだ。

 次回はSubプロシージャと対をなす、Functionプロシージャについて説明する。End of Article


 INDEX
  [基礎解説]チェック式 WSH入門
  第7回 Subプロシージャでユーザー独自の処理を定義する
    1.Subプロシージャとは
    2.Subプロシージャと引数(1)
  3.Subプロシージャと引数(2)
 
 基礎解説

ホワイトペーパーTechTargetジャパン

Windows Server Insider フォーラム 新着記事

@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

RSSフィード

スキルアップ/キャリアアップ(JOB@IT)

- PR -
- PR -

お勧め求人情報

キャリアアップ 〜JOB@IT
@IT Special -PR-
  企業の仮想化に足りない“発想”とは?
仮想化運用管理のキモは意外なところに!

New!
  操作もマニュアルも分かりやすい!
ユーザー視点で開発されたPC管理ツール

New!
  仮想化すればコストは削減できるか?
仮想化に必要な「3つの視点」を解説する

  セキュリティを知り尽くす上野氏が登壇!
@ITメールソリューションLive! in Tokyo

  運用管理の課題を“2つの観点”から分析
ユーザー満足度の高い「仮想環境」とは?

  世界に通用するストレージの作り方とは?
製品に込めた思いを富士通の開発者に聞く

  OSSで手間も時間も、障害も減った――
「マピオンの事例」オープンソース活用法

  「ノートPCの持ち出し禁止」で大丈夫?
情報漏えいを防ぐ管理手法とインフラは?

  1日の処理を1秒に――MySQLの達人が語る
「コスト削減」できるチューニング

  ドキュメント作成を自動化して、SEの作業
効率を大幅アップ! Visio 2007の魅力

  急速に広がるHyper-Vでのサーバ仮想化
そのベストプラクティスをデルが解説

  @IT主催セミナーで語られた、「担当者に
求められるセキュリティ対策」をレポート

  @IT「Windows 7」 特設サイトオープン!
最新情報・移行ノウハウを公開しています