見出し画像

0から始めるPHPプログラミング #1-3 VBAで入力チェックを実装する その3

―――個人情報入力フォームへの入力チェック機能の実装が無事完了しました。

では、保護者の皆さんにこのフォームをメールで送りましょう。

あなたは早速、メールソフトを開き、入学式の日に収集した各メールアドレス宛てに案内文と添付ファイルを送ろうとしました。

そんなときです・・・。


―――ちょまてよ(キムタク風)


どこからともなく声が聞こえてきました。

え?あなたは誰ですか?


―――そのファイル、本当に送っちまっていいのかい?


なんということでしょう。脳に直接届いた謎の声はファイルの送信を制止してくるではありませんか。


あなたは言葉の意味をしばし考えることにしたのでした―――


入力チェックを実装する ~中級編その1~

はい、章タイトルが中級編になりました。

前回は入力チェックが必要な各項目に対してチェック処理を実装しました。

必須チェックと形式チェックを完成させて、想定外の入力値はセルに直接入力規則を設けるという方法で対応したんでしたね。

一応完成はしたのですが、冒頭の茶番みたいな件の通り、まだユーザに向けて送るのは早そうです。このままでは送れないと。

そう、実はまだ完成度としては低いんです。どうして低いのか?という説明も含めて続きの実装をしていきましょう。

入力チェックの仕様としては新しい要素が入ることはありませんが、これまでとは少し違う方法で実装していただきます。


今回はずばり、ループ処理を行います。IF文が分岐処理で、ループ処理はそれと並ぶくらい基本中の基本であり、かつプログラムの大切な一要素です。

先ほど、「完成度が低い」と申しました。

まあ各項目に対してきちんと実装した身としては

なんてこと言うんだ!!

って感じですよね。

では例えばですよ、あなたは「身長」という項目を追加したいと思いました。入学時の身長を入力いただく項目です。それを・・・

001_身長追加

こんな風に追加したとしましょう。赤枠のところね(青枠はこのあと触れる項目群)。

あ、あなたも以下のように追加してください。

002-1_行コピー

8行目の赤枠内で左クリックします。すると行選択の状態になるので、Ctrl + Cでコピーします。

そして・・・

002-2_行挿入

9行目を同じく左クリックし行選択、その状態で右クリックしてメニューを出します。メニューに「コピーしたセルの挿入」というのがあるので、クリックしましょう

002-3_行挿入成功

こんな風になればOK。

最後に、セルの内容を適切に編集します。9行目の「卒園名」を「身長」に、「PHP認定こども園」を空白にしましょう。

002-4_行挿入成功後編集

さて、これでOK。次に進みます。


これをした途端、今追加した身長行以降の必須チェックは破綻します

全部、セルの場所を決め打ちしていますからね。

ためしに実行してみると・・・

002_身長追加後バグ

エラーが出ました。

エラーメッセージが表示されている項目は実際には値が入力されています。にもかかわらずエラーとなるのは実際にチェック対象となっているのは上図の赤枠のセルだからです。

そして、エラーメッセージが出ていない項目も実際にチェックされているのは異なる項目です。例えば氏名項目のチェックはふりがな項目の入力値に対して行っていますね。1行ずれてるわけだから。

電話番号にかぶっているところはややこしいですが、実際に電話番号の値があるセルはB列です(赤枠はC列)。文字を中央寄せにしているので、ちょっとわかりにくくなってます。


冒頭の件の答え合わせですが、どうしてまだファイルを送るべきでないのか?どうして入力チェックとしての完成度が低いのか?というと、今はまだ拡張性を無視した実装になっているからです。

拡張性というのは例えば先ほど「身長」項目を追加したみたいに、フォームに変更があっても、プログラムの修正をしないで(もしくは最低限の修正で)機能としての振る舞いを維持することです。


では、今回みたいに1行途中に挿入しても処理を問題なく行うにはどのようにすればいいでしょうか。

これは頭の使いどころですね。ちょっとしたクイズですから。

考えてみてください。



めっちゃもったいぶりたい私・・・!



では、答えいきましょうかね。


答えは、入力チェックの対象かどうかにかかわらず、全項目を走査していく、です。

走査(そうさ)というのは先頭から順番に確認していく、ということです。1行1行を対象に繰り返し処理をする、つまりループ処理です。


では実装の下準備をしましょう。

前回までで実装いただいたソースは不要になりますが、消すのはもったいないです。あれはあれでアリっちゃアリなので。

そこで、新しいマクロを用意しましょう。

入力チェックボタンの上で右クリックをしてメニューから「マクロの登録」を選択してください

003_新しいマクロ

すると・・・

004_マクロの登録

このようなダイアログが出てきます。赤枠内にあるのは今ボタンに紐づけられてるマクロです。そこを一度クリアして、新しい名前を入れましょう。

005_マクロ名入力

前々回のあとがきに「次はマクロ名を英名にするよ」という話をしてました。「Validation2」を入力しましょう。Validation(ばりでーしょん)には検証という意味があります。

入力できたら右にある新規作成ボタンを押下してください。

006_モジュール2

はい、このように新しくソース編集の画面がでてきたらOKです。私の画面、ローカルウィンドウが下につぶれてますね。

Validation2と入れたけど、validation2になってるのはよいですこれで。)

ちなみに、前回までのソースを見たい場合は、左メニューにある「標準モジュール」という欄の「Module1」をダブルクリックしてください。そこで切り替えられます(上図赤枠)。

今の操作で入力チェックボタンはこのvalidation2というマクロに紐づいています。だから今ボタンを押しても何も起こりません。


それでは、手始めに簡単なループ処理を実装してもらいましょう。今の入力チェックとは関係ないことをやります。なので、あくまで練習。このソースは後で消します。

次のソースを下図のように実装してください。

    For i = 1 To 40
  
       Cells(i, 12).Value = i
  
    Next

007_初めてのループ

ループのことはForループ(ふぉーるーぷ)と呼んだりします。ではまずはループ構文を確認しましょう。

For ループ変数 = 初期値 To 最大値
 繰り返し行う処理
Next

固定なのはFor(ふぉー)To(とぅー)Next(ねくすと)ですね。ほかの部分は任意の内容にできますが、慣例もあります。

まず、ループ変数。ループ変数というのはカウンタ変数というとよりわかりやすいかもしれません。ループが何週目か?を管理するための変数です。この変数名にはプログラミング界の慣例で「i」が使用されます。

前回、変数名は重要だって話をしたので、「i」ってなんか矛盾してる気がしないでもないですが、この世界では i といえばループ変数なのでOKなんです。

そして、そのループ変数には初期値を代入します。1を入れてますね。ここでも右辺から左辺に代入する点は通常の代入と同じです。

    For i = 1 To 40

繰り返し処理の最初は1回目なんだから1じゃないのか、とお思いになるかもしれませんが、ちょっと違うんですね。この辺りは入力チェックのときに触れましょう。

で、Toの次に最大値を書きました。最大値はループ終了値と考えてください。今回は40と書きましたが、ここが注意で「To 40」と書いてあったら必ず40回繰り返すわけではありません。

正しくは変数 i の値が40に到達するまで繰り返す、です。

だから変数 i の初期値が38だったら3回で終了ですし、1だったら40回繰り返します。

そして、繰り返しの処理を終えたところで「Next」という記載があります。これはここまでがループ処理の塊ですよ~と示すためですね。「Next」すなわち「」なので、ここまで来たら次のループに移行します、ということです。

Nextのタイミングでループ変数は自動的に+1されます。プラス1することをインクリメントといいます(-1はデクリメント)。

では、動作確認の前にソースの内容からどんな処理が実行されるかを想像してみてください。

    For i = 1 To 40
  
       Cells(i, 12).Value = i
  
    Next

ループ変数 i が1から始まり40までぐるぐると繰り返し処理を行います。

処理内容は i 番目の行の12列目のセルに変数 i の値を設定します。

ではでは、どうなるのか・・・いざ実行!入力チェックボタンをポチっとな。

008_ループ実行

はい、一瞬でぱっと数字が表示されたかと思います。

そうですね。プログラムがやってくれました。これがループ処理です。

で、練習のためのソースだとしてもこれだけではあまりに芸がない。ちょっとひねったことしてみたいですよね。


というわけで、アレやりましょう。世界のナベアツ。


若い人はわからないかもしれませんが、2000年代後半にちょっとブレイクした芸人に「世界のナベアツ」という人がいたんですよ。全然世界規模では活躍してませんでしたけどね。

で、当時その人が十八番としていた芸に数字を1からカウントしていく中で、「3」の倍数と「3」がつく数字の時だけあほになる、というのがありました。

Youtubeの動画貼ってますが、もしも見られなかったらYouTube上で直接検索して探してみてください。見ていただいた方がこの後何をやるのかイメージしやすいので。



先ほどは単純に1から40までインクリメントを繰り返しただけでした。そこで、「3」の倍数と「3」がつく数字の時だけ通常時とは異なる処理をしてみましょう。

値が特定の条件に合致するときだけ別の処理を行う・・・もうわかりますね。はい、ここでもIf文の登場です。

では、早速実装してみます。段階を踏んでいきますね。

まずは先ほどの

Cells(i, 12).Value = i

Cells(i, 12).Value = "(・´з`・){" & i

に変更してください。

009_なべあつ実装1

これでまず実行するとですね・・・

010_実行結果

はい、リラックスした表情でカウントしてくれています。
(ここの顔文字、あなたのお好みのものに変えていただいていいんで!!)

"(・´з`・){" & i

これは文字列とループ変数 i を & を使って連結しています。

2つの文字列は「&」を使えば連結できる、というのはこれまでにもやりましたね。複数のエラーメッセージを連結してmessage変数に入れたのでした。

最初に顔文字と吹き出し記号、「&」を挟んで変数 i を連結したため、上図のようにまるで顔文字がカウントしてくれているような表示ができました。

次の項で本格的に世界のナベアツ作りを進めます。


世界のナベアツを実装しよう

それではIf文を使いたいのですが、今回はこれまでと違って条件式で確認したいことが2つあるんですよね。

・3の倍数なのか
・3がつく数字なのか

そしてこれらのどちらかを満たせばアホになりたいんです。

このように複数の条件の中でどれかひとつに合致すればいいものをOR条件(おあじょうけん)といいます。

If 条件A Or 条件B Then
 条件Aと条件Bのどちらかを満たしたときに実施する処理
END If

(↑条件A,Bのみで示していますが、条件C,D,E・・・とつなげていくことも可能です。あまりたくさんをつなげることはしないけども。)


まずは3の倍数かどうかを判定する方法。突然あなたに聞いちゃいますけど、どんな方法を使えば繰り返し+1しながら流れてくる数字を3の倍数かどうか判断できると思います?

こういうこと考えるのがプログラミングの醍醐味だと思うんですよね。


ここでパッと答えが浮かばなかったからといって挫けないでほしい。そこはあまり重要じゃないです。知ってるかどうかだけの話。一度知ってしまえばこっちのものだから。


1,2,3,4,5,6,7,8,9という数字があったとき、とある条件にかけたら3,6,91,2,4,5,7,8のグループに分けることができる、ということです。

3の倍数って言ってますから、掛け算割り算辺りがなんか怪しいですね。

では、ためしに各数字を3で割ってみましょう。

1 ÷ 3 = 0…あまり1
2 ÷ 3 = 0…あまり2
 ÷ 3 = 1…あまり
4 ÷ 3 = 1…あまり1
5 ÷ 3 = 1…あまり2
 ÷ 3 = 2…あまり
7 ÷ 3 = 2…あまり1
8 ÷ 3 = 2…あまり2
 ÷ 3 = 3…あまり

はい、わかりましたかね。3の倍数は必ず余りが0になります

では、その条件をソースコードに反映しましょう。

    For i = 1 To 40
      
        If i Mod 3 = 0 Then
          
        Else
      
            Cells(i, 12).Value = "(・´з`・){" & i
      
        End If
      
    Next

こんな風になります。前回もElse(えるす)が出てきましたけど、今回も使います。この処理では例の2条件に合致したかどうかで

・普通にカウントする
・アホになってカウントする

のどちらか片方を表裏一体の処理として行うので必要ですね。

さて、肝心の3の倍数かどうかの判定ロジックです。

If i Mod 3 = 0 Then

Mod」というのが出てきました。これはモジュロと呼ぶのがよさそうです。私も今の今まで知らなかったんですけど、wikipediaにそう書いてありました。

これは割り算の余りを出したいときに使います。

今回の場合、変数 i ÷ 3 の余りを出すために使います。そのあまりの値が0と等しいかどうかをこのIf条件では検証していますね。

が、ここちょっとわかりにくいなあ・・・。段階を踏みましょう。

すみません、Forループが始まる前に、次の変数を追加してください。

    '除算の余りを格納
    Dim modResult As Integer

そしてForループが始まった後に以下の処理を追加、下図のようにしましょう。

'ループ値 ÷ 3 の余りを代入
modResult = i Mod 3

011-2-1_なべあつ実装

計算結果を一度変数に格納した上で、If文の条件に使用しています。

この方が余りの値を変数modResultがもっていることが明確にわかっていいですね。


もうひとつの条件にいきましょう。「3のつく数字かどうか」です。これはいくつかやり方があるのですが、今回はそのうちのひとつ、LIKE(らいく)を使う方法でいきます。

ある文字列中にある値が存在するかどうか?を確認したいときに使います。

今回で言うと変数 i の中に「3」が含まれるかどうかを確認したいんですね。

それは、こんな風に書きます。

i Like "*3*"

という書き方をするのですが、3の両隣にアスタリスクをつけているじゃないですか。これは説明しだすと長いんで、今回のあとがきで説明します。

さて、OR条件という話でしたね。

Sub validation2()

   '除算の余りを格納
   Dim modResult As Integer

   For i = 1 To 40
   
       'ループ値 ÷ 3 の余りを代入
       modResult = i Mod 3
     
       If modResult = 0 Or i Like "*3*" Then
           
         
       Else
     
           Cells(i, 12).Value = "(・´з`・){" & i
     
       End If
     
   Next
   
End Sub

このように書きましょう。

011-2_なべあつ実装

今、この状態で実行したらどうなると思います?

3の倍数もしくは3のつく数字のときは、If文の中になにも処理を書いていません。3の倍数でもないし、3がつくわけでもないとき(Elseに入ったとき)にセルに値を設定する、としています。

つまり・・・

012_実行結果2

はい、そうです。アホにならない時の数字だけカウントしています(一度列の内容を削除してから実行しました)。

ではでは、次にやることはもうわかりますよね。アホになるときの処理を追記します。

Cells(i, 12).Value = "(*''▽''){" & i & "!!"
Cells(i, 12).Font.Bold = True

これをあのOR条件の中に書きましょう。

処理の説明ですが、1行目はわかりますよね。セルに値を設定しています。「&」を複数使っていくつかの文字列を連結することもできます。

2行目はセルのフォントの太さを設定しています。

前々回の記事で

Valueの前に「.」←これがついているじゃないですか。ドット。
これは「の」と解釈してください。
Range("B4").Value → 「B4セル」 「の」 「値」

こんな説明をしました。今回も同じ理屈です。実はセルって「Value」以外にもいろんな情報を持っています。そのひとつが今回登場した「Font」です。

Cells(i, 12).Font.Bold = True

FontもFontでいろんな要素をもっています。色とか太さとか字体とか。で、その要素によってどんな値を指定するか?は変わってくるんです。

ここでは詳細な説明は避けるけど、色だったらいろんな色がExcel側で数字で管理されているので、数字を設定します。今回の太さ(bold)はON/OFFで指定します。太いか?太くないか?の2択だからです。

プログラミングの世界ではこのON/OFFの2択をTrue/Falseで設定します。

True(とぅるー)、False(ふぉるす)と読みます。

前々回データ型というものが初登場したとき

データの型には数値型や配列型、真偽型などがありますが、(以下略)

という説明をしましたが、True/Falseはこの真偽型のデータに設定する値です。真か偽か、表裏一体なんですね。つまり下記ソースは

Cells(i, 12).Font.Bold = True

i 行目12列目のセル(Cells(i, 12))
の(.)
フォント(Font)
の(.)
太さ(Bold)
にTrueを設定しています。TrueはON、つまり太くするよう指定しています。

動画見てもらえたかわかりませんが、アホになるときちょっと主張強いんでね、そこを太字で表現します。

011-3_なべあつ実装

こんな風に書ければOK。

では、さっき実行した分の表示を一度削除しましょう。

014_列削除

列単位で一気に削除したいときは列選択をして、Deleteキーを押せばOKです。

ではね、

015_実行前

この状態でいよいよ実行してみますか。

入力チェックボタンをポチっと押してみてください。

016_実行結果1

017_実行結果2

018_実行結果3

うおおおおおおおおおおおおおお!!!!!!!!!!!!!!!!!

世界のナベアツキタ━━━━(゚∀゚)━━━━!!━━━━(゚∀゚)━━━━!!

NA――BE――A――TSU――!!!!!!!!!!! YEAH~~~~~~!!!!!!


はい、テンション上がってしまいましたね。

今引いたり冷めたりしたあなた!!野暮ですよ!!ヤボ!!

世界のナベアツにまた会えたんだから!!別にファンでもないけど!!


・・・ん、ゴホン。失礼しました。なんかデジャブ感ありましたね。


これでループ処理の練習は終わりです。


ループ処理中に分岐ロジックを使うことで、その時のデータの状態に応じていろんな処理に振り分けることができます。

今回ならカウント数に従ってアホになるかどうかを分岐処理で実装しました。

お遊びに思えたかもしれませんけど、これは結構プログラミングの本髄をついています。人間が頭使ってアレコレやるのをコンピュータでもできるような形にするのがプログラミングですから。

ナベアツさんのあの芸中の頭の中をプログラミングで表現してみました、ということですね。

では、ここまでやったことを踏まえて、入力項目の必須チェックをやってみましょう。


入力チェックを実装する ~中級編その2~

ループ処理の概要はここまでで理解いただけたと思うので、入力チェックの実装に進んでいきましょう。

さきほど、入力チェックの対象かどうかにかかわらず、全項目を走査していく、という話をしました。

なので、項目が並んでいるところを・・・

019_ループ方向

この矢印のようにザーーっとみていきます。

この「みていきます」はIf文の条件式(=項目名がアスタリスクを含んでいるかどうか)にかけていきます、という意味です。


実はもうひとつ説明したいことがあるので、小出しに進めていきますね。

まず、先ほどのナベアツソースは削除しましょう。
さようなら、ナベアツ・・・(寂。

023_さようならなべあつ


さて、ここから説明したいのは関数(かんすう)ですが、まずは以下のソースを貼り付けてください。

    '項目名
    Dim itemName As String
    '項目値
    Dim itemValue As String
    'アスタリスクの出現ポイント
    Dim asteriskPoint As Integer
    'メッセージ
    Dim message As String

    For i = 4 To 30
   
        '項目名を代入
        itemName = Cells(i, 1).Value
       
        '項目値を代入
        itemValue = Cells(i, 2).Value
   
        '項目名中のアスタリスクの出現位置を代入
        asteriskPoint = InStr(itemName, "*")
          
        If asteriskPoint > 0 Then
           
            Debug.Print i & "行目の項目:" & itemName & vbCrLf & _
                        " アスタリスクが登場するのは " & asteriskPoint & "番目です。"
          
        End If
      
    Next

020-2_ソース

先ほどと同じ、ループ処理をしていますね。ちらほら見慣れないものがいます。

今回、ループ変数は4から始まり30でおわります。この数字の根拠はどこにあるのかというと・・・

021_4行目から

022_30行目まで

入力フォームの始まりの行が4行目で、終わりの行が30行目なんですね。

ナベアツのときは1からカウントしたいからループ変数の初期値を1に設定しましたが、今回は入力フォーム外である1~3行目は処理の対象にしたところで仕方ないので、いきなり4から始まるようにしました。

そして、同様に31行目以降は入力フォームの外なので項目名を確認しても意味がありません。項目がそもそもないので。なので30をループの終了値としています。


関数の説明の前にソースの解説をしていきましょう。

    '項目名
    Dim itemName As String
    '項目値
    Dim itemValue As String
    'アスタリスクの出現ポイント
    Dim asteriskPoint As Integer
    'メッセージ
    Dim message As String

そろそろ見慣れてきたでしょうか。変数宣言です。

Dim 変数名 As データ型

という書き方をするんでしたね。後続処理で使用する変数を宣言しました。itemName、itemValue、messageはいいとして、asteriskPointはこの時点ではよくわかりませんね。この後の説明で触れます。

変数が出てきたときの捉え方としては

ああ、この後の処理でこれらの変数を使うのね、はいはい

くらいでいいです。この時点ではただ変数がある、というだけの状態です。


次。

    For i = 4 To 30
   
       '項目名を代入
       itemName = Cells(i, 1).Value
       
       '項目値を代入
       itemValue = Cells(i, 2).Value

Forループが始まりました。最初に代入処理をしていますね。エクセルの入力フォームを見ていただければわかりますが、1列目は項目名、2列目は各項目の入力枠です(もちろん他の列にも項目名、項目値はあるけど、今はここだけとします)。

Cells関数は Cells(行番号 , 列番号) と指定するので、説明と一致します。i行目の1列目、i 行目の2列名の値をそれぞれ変数に代入しています。

ループに入ってから最初にこの代入処理があるということは、この代入された変数がこの後の処理に登場する、ということですね。

複数回登場する値は変数に入れるのがよいです。毎回Cells(i,1).Valueって書くの大変ですし、何より変数があることで可読性が向上しますから。


次!

        '項目名中のアスタリスクの出現位置を代入
       asteriskPoint = InStr(itemName, "*")

InStr(いんすとりんぐ)という関数のお出ましです。

ここでInStr関数をモデルに関数(かんすう)についてご説明しましょう。

関数というのは英語で言うとfunction(ファンクション)、つまり機能という意味です。

でも私、過去の記事でマクロの説明するときも・・・

要するになにかしらの機能ですね。ソースコードを書いてマクロを作ることをマクロを組むなんて言います。

って言ったんですよ。また機能かいと。でもこう考えてください。マクロはひとつのパッケージされたシステムです。これと比較すると関数はシステムを構成するための部品や歯車という感じです。

日常にある部品や工具をイメージしてほしいんですけど、これらは用途や条件が同じであれば再利用ができるんですよね。この点はプログラミングの関数もまったく同じです。

部品や歯車(=関数)を組み合わせて機能(=マクロ)を作る、という感じです。マクロは大きい単位の機能、関数は小さい単位の機能(=処理)と、捉えてください。

で、関数とセットで覚えてほしいのが、

・引数(ひきすう)

・戻り値(もどりち)

です。

この後の説明のために、先に頭に入れておいてほしいのが、InStr関数が提供してくれる処理の内容です。InStr関数は1つ目に指定した文字列の中に2つ目に指定した文字が最初に登場する場所を数字で返す、という働きをします。

そして関数は・・・

関数(=処理)に対して処理に必要な
材料(=引数)を渡して、
結果(=戻り値)を受け取る

という風に使います。InStr関数でみてみましょう。

        '項目名中のアスタリスクの出現位置を代入
        asteriskPoint = InStr(itemName, "*")

このように関数を使用することを「関数を呼び出す」なんて言い方をします。引数は関数の定義によって、複数指定することができ、今回なら・・

戻り値 = InStr(第一引数 , 第二引数)

というように、引数、戻り値が当てはまります。

「InStr」の後に続く括弧の中に指定しているのが、引数です。1つ目の引数を第一引数(だいいちひきすう)、2つ目の引数を第二引数(だいにひきすう)、3つ目を・・・以下略、と呼びます。

        '項目名中のアスタリスクの出現位置を代入
        asteriskPoint = InStr(itemName, "*")

今回、InStr関数に渡されている処理に必要な材料(=引数)は

itemName,"*"

この部分のことで、itemName第一引数"*"第二引数となります。


なので、今回なら第一引数にitemName変数を指定し、第二引数には"*"を指定している、というわけです。引数への指定は変数でも固定の文字列でも可能です。固定の文字列のことを定数といいます。

定数は後続記事でまた扱いますね。


        '項目名中のアスタリスクの出現位置を代入
        asteriskPoint = InStr(itemName, "*")

そして、このInStr関数が返してくれる値をasteriskPointという変数に代入していますが、この代入している値を戻り値といいます。関数から呼び出し元に戻ってくる値だから戻り値です。

ですので、例えばループの1週目は「ふりがな*」という文字列がitemNameに入ってきますが、その結果、asteriskPointには5が代入されます。アスタリスクが5番目にありますからね。この「5」が戻り値です。

あとで動作確認します。


ここまで説明すると

実際にInstr関数の処理内容を見てみたい!

という方がいるかもしれません。

その気持ちはわかります。でもその必要はないんです。先ほども関数は部品や歯車という風にお伝えしました。私たちは何か目的の処理があったらそれを叶えてくれる部品(=関数)を便利に利用すればいいだけなんです。

先人たちが

この処理はいろんなシステムで使うから、もう部品化してしまおう

という風にしてくれたんです。

私たちがやるのは関数に対して処理に必要な材料(=引数)を渡して、結果(=戻り値)を受け取るだけです。

ただ、ソースの中身が見たいわけじゃなくても一体どういう関数なんだよ!ということはあると思います。ちゃんと公式リファレンスがあるんですね。

公式リファレンスというのは、この場合VBAというプログラミング言語を作った組織/団体が提供している関数の説明書みたいなものです。

↑こちらをご覧ください。ページ名の「InStr」の横に「(Visual Basic for Applifations)」ってあるじゃないですか。これはライブラリの名前です。

正規表現の実装をするときに、ライブラリを追加しましたよね。(ライブラリはいろんな処理(=関数)が定義されてる便利なお道具箱みたいなもの)

024_ライブラリ

上部メニューの「ツール」>「参照設定」から開けるこのライブラリ一覧の一番上(上図赤枠)に同じ名前のものがあります。つまり、このライブラリの中にInStr関数があります。


こういう思想はプログラミング全体であるので、覚えておいてください。便利な部品は先人が用意してくれているので、どんどん活用していくこと。

で、「やりたい処理を提供してくれる関数がないぞ」となったときに初めて自分で関数を作るんです。そう、関数は自分でも作ることができるんですね。

そこは次回やります。関数の説明としてはここまでです。


ソースの続きを見ていきましょう。

        If asteriskPoint > 0 Then
           
            Debug.Print i & "行目の項目:" & itemName & vbCrLf & _
                        " アスタリスクが登場するのは " & asteriskPoint & "番目です。"
          
        End If

はい、If文です。

先ほど、itemNameが「ふりがな*」だったらasteristPoint変数には5が入っている、という話をしました。InStr関数はアスタリスクの出現位置を返してくれる関数ですからね。

で、それが0より大きいかどうかを判定していますと。

ここまで、アスタリスクを含むケースばかりで説明してきていますが、

アスタリスクを含まなかったら戻り値は何になるんだ

と、気になるでしょう。わざわざデバッグで確認するのもいいですが、ループ処理だし、少し面倒そうです。

そういうときに先ほどの公式リファレンスの登場ですね。


029_公式リファレンス読み方1

まず、構文の欄を参照しましょう。ここでは、第一引数を「String1」、第二引数を「String2」として表現されています。これを理解した上で戻り値の欄を見てみます。

028_公式リファレンス読み方2

戻り値にもいろいろパターンがあるんですよね。

で、赤枠で囲いましたところが今の説明の対象です。第二引数が第一引数中に見つからなかった場合の戻り値・・・「0」となっていますね。はい、数字の「0」を返してきます。

そして話をソースに戻しますと・・・

        If asteriskPoint > 0 Then
           
            Debug.Print i & "行目の項目:" & itemName & vbCrLf & _
                        " アスタリスクが登場するのは " & asteriskPoint & "番目です。"
          
        End If

項目名(itemName)にアスタリスクが含まれない場合はasteriskPoint変数の値は「0」になります。

これはつまり、itemNameにアスタリスクが含まれていたらTrueを、含まれていなかったらFalseを返す、というロジックです。

Cells(i, 12).Font.Bold = True

ナベアツループのところで↑真偽値の解説したじゃないですか。TrueかFalseを設定するっていうの。

今までそういう言い方を避けてきましたが、If文の条件式に指定するのも真偽値です。条件に一致するか?しないか?の2択ですので。

真偽値ってことはTrue(条件に一致する)False(条件に一致しない)のどちらかを返します。

「ふりがな*」の場合、実質的には以下のソースの条件式になります。

        If 5 > 0 Then
           
            Debug.Print i & "行目の項目:" & itemName & vbCrLf & _
                        " アスタリスクが登場するのは " & asteriskPoint & "番目です。"
          
        End If

5は0より大きいか?という小学生でもわかるような式。これは当然、結果が真ですからTrueを返します。

さっきから「返します」という言い回しを使っていますが、これもさっきの関数の説明に出てきた戻り値をイメージしてください。条件式の結果をIf文に返して(戻して)くれているんです。



さて、If文の条件式が理解できたら中の処理に進みましょう。

Debug.Print i & "行目の項目:" & itemName & vbCrLf & _
            " アスタリスクが登場するのは " & asteriskPoint & "番目です。"

これまた初出です。「Debug.Print(でばっぐぷりんと)」。

以前、デバッグのやり方をお伝えしましたよね。ブレークポイントを設定して変数の中身を追っていく、というの。

あの時は短い処理だったからF8キーを押しながらひとつひとつ変数の値の変遷を確認できましたけど、ループ処理で同じことをするのは面倒だと思いませんか?・・・面倒ですっ!!

100周とか1000周あるループだったら絶対イヤですね!


そういう時に使える方法なんです、Debug.Printは。もちろんループ処理以外で使うのも有効です。

使い方をお教えします。

開発画面上部のメニューから「表示」を開いて「イミディエイト ウィンドウ」を選択しましょう。

025_イミディエイトウィンドウ

いみでぃえいと うぃんどう・・・言いにくいな。

さて、

026_イミディエイトウィンドウ出した

こんな風になればOKです。イミディエイトウィンドウとローカルウィンドウが下の方に潰れていたらソース画面との境目辺りにマウスを合わせて上に引っ張ってください。

では、この開発画面がアクティブな状態で、F5キーを押下しましょう。

アクティブな状態、とは今コントロールがある状態、ということです。よくわからなかったら、ソース画面を一度左クリックしてもらえばそれがアクティブな状態です。


F5キーは実行ボタンのショートカットです。

027_実行

イミディエイトウィンドウにこのように表示されていれば成功です。

Debug.Printは指定した値をイミディエイトウィンドウに表示する処理なんですね。そしてその内容にも注目してください。

Ifの条件式の説明でお伝えしたように、項目名にアスタリスクを含むときのみTrueとなるので、アスタリスクがある時だけ、If文の中の処理を実行しています。卒園名とか身長の項目はありませんからね。


もしかすると、

どうしてアスタリスクが何番目にあるかを出力させるのか?

という方がいるかもしれません。

今回はループとInStr関数の説明をメインにお届けしたので、ループの周回ごとの取得した項目名によって、ちゃんとInStr関数の戻り値が異なっていることをその目で確認してほしかったからです。

処理内容としてはループ内で必須項目かどうかを判別するためにIf文を構えているので、その動きを確認いただきました。


説明を続けましょう。

Debug.Print i & "行目の項目:" & itemName & vbCrLf & _
            " アスタリスクが登場するのは " & asteriskPoint & "番目です。"

この↑文字列には変数が3つ仕込まれていて、それぞれループごとに値が異なるのが、イミディエイトウィンドウで確認できます。

この処理の1行目の最後に「_」があるじゃないですか。アンダーバー。

これは処理としては1行なんだけど、ソースの記載上では改行したいときに使います。次の行も同じ処理の一部だよ、ということです。

もちろん、1行で書ききってもいいですが、横スクロールが発生すると面倒なので、そのあたり考慮しています。

これも可読性への配慮、美しいソースを書くためのお作法です。


残りのソースも触れておきましょう。

        If asteriskPoint > 0 Then
           
           Debug.Print i & "行目の項目:" & itemName & vbCrLf & _
                       " アスタリスクが登場するのは " & asteriskPoint & "番目です。"
          
       End If
      
   Next
   
End Sub

はい、End IfでIf文を閉じています。そしてその直後に「Next」がありますね。次のループに参ります、ということです。

最後にEnd Subがありますが、これはソースの1行目の

Sub validation2()

と対になるので、処理の終わりを示していますね。


今回はここまでにしましょう。ループによる入力チェックの布石的内容でした。

Ctrl + Sで保存しておいてください。



あとがき・ふりかえり

はい、今回もありがとうございました。お疲れさまでした。

以下の2つを伝えておきます。

・ワイルドカード
・プログラミング言語のバージョンについて

--  --  --  

・ワイルドカード

途中であとがきで説明しますって言った件がありましたよね。あれを説明します。

検索対象の文字列 Like 検索文字列
という書き方をするのですが、3の両隣にアスタリスクをつけているじゃないですか。これは説明しだすと長いんで、今回のあとがきで説明します。

これですね。ナベアツのループをするときに変数 i が「3」を含むかどうかを検証したい処理で

If modResult = 0 Or i Like "*3*" Then

こんな風に書いていました。

このアスタリスクはワイルドカードといいます。

ワイルドカード・・・めっちゃかっこよくないですか笑。中2心をくすぐりまくる!

これは・・・ん~トランプでやる大富豪ってゲームあるじゃないですか。あれで言うところのジョーカーの役割ですね。

ちょっと特殊なやつでなんにでもなれるんです。

i Like "*3*"

このように3の前後にアスタリスクがある場合は、そのアスタリスクの代わりに何か文字があってもOK!という意味です。

次の説明がわかりやすいかなと・・。

If i Like "3" Then

こういうIf文の場合、変数 i の値は「3」と完全一致でないといけません。

If i Like "3*" Then

こういうIf文の場合、変数 i の値は「3」から始まる値でないといけません。その後ろにどんな文字列がつづいてもOK。

If i Like "*3" Then

こういうIf文の場合、変数 i の値は「3」で終わる値じゃないといけません。その前にどんな文字列があってもOK。

つまり、アスタリスクはなにかしらの文字の代わりをするんですね。

だから、文字列中のどこかに「3」を含んでてほしい!という場合は

If i Like "*3*" Then

このような書き方をします。

ちなみに、後半のInStr関数のところではこの方法を使いませんでした。

「*」←この文字を含むかどうかを検証したいからできそうなものですが、なぜでしょうか。

はい、このような特殊文字は処理できないんですね(探したら方法があるかもしれませんが)。ですので、InStr関数を使いました。

プログラミングではちょいちょいこういう問題にぶち当たります。例えば

文字列をダブルクォーテーションで括って書くんだけど、その文字列中にダブルクォーテーションを書きたい場合はどのように書けばいいんだ?

とかですね。

はい、ワイルドカードの説明はここまで。


--  --  --

・プログラミング言語のバージョンについて

今回、公式リファレンスというのが出てきましたよね。プログラミング言語は神様が作ったわけではなく、どこかの頭のいい人たちが作ったものです。

それを多くのプログラマーが利用してシステムを作るわけですから、当然みんなが使いやすいように公式リファレンスというものが存在します。

そして、プログラミング言語にはバージョンというものがあります。

世の中のガジェットやあらゆる機器にもバージョンは存在しますよね。身近なところだとスマートPhoneとか。

で、プログラミング言語のバージョンでひとつ注意したいのが、バージョンアップによって、今まで問題なく使用できていた関数が使えなくなるケースがある、ということです。

実際には突然使えなくなるというよりは、提供団体が「非推奨」に指定してくる、という感じですがね。

もちろん、バージョンアップですから逆に便利になることも多々あります。これまでできなかったことができるようになった!!なんてね。

まあ、そういう話があるんだな、程度に覚えておいてください。

余談でした。


おわりに

おわりです!

もっとサクサクと進めたいんですが、どうしてもコーディングの基本事項やデバッグのテクニックなんかに触れだすと説明に文字を割きすぎてしまいます。

ただ、この連載のモットーとして長期的に見て本当に身になるプログラミングスキルの獲得を掲げていますので、将来的に見て有効な内容だと思ってもう少しついてきてください。

PHPの連載なんだからはやくPHPしたいですよね・・・。私もやりたい。

もうしばらくの辛抱です!

最初の方で基本的なことを抑えたらあとはサクサク進むので!


では、おわりで~す。今回もありがとうございました。

ゆっくり休んでくださいね(∩´∀`)∩。


この記事が気に入ったらサポートをしてみませんか?