0から始めるPHPプログラミング #1-2 VBAで入力チェックを実装する その2
こんにちは。
前回は「ふりがな」項目に対して必須チェックの実装を行いましたね。
関数、変数、データ型、If構文、ハードコーディング・・・などいろんな言葉が一気に出てきました。が、今の時点ではどれもちゃんと理解する必要はありません。
連載を通して覚えるというよりも体に馴染んできますので、習うより慣れろの精神で、この回もぼちぼちやっていきましょう。
では、早速始めます!
(今回はちょっと長いです。すみません。)
入力チェックを実装する ~初級編その2~
前回は初級編その0とその1に取り組んでいただきました。
入力様式の内容を把握してボタンを設置、そしてボタン押下による入力チェックを「ふりがな」項目のみに対して実装したのでしたね。
このようなソースでした。
ファイルを閉じていた方はエクセルのこのファイルを開いて、Alt + F11キーを押下するとコーディングの画面を出すことができます。その結果、もしもソースが開いていなかったら左メニューから「Module1」をダブルクリックしてください。
さて、説明です。
Range("B4").Valueがふりがな項目に入力された値を示すので、それが空文字(からもじ)なのかどうかを確認したんでしたよね。
空文字だったら「ふりがなが入力されていません」という文言がmessage変数に設定されて、最後にメッセージボックスとして出力されるのでした。
ではここからは、ふりがなと同じ要領でほかの項目についてもチェックを実装いただけばいいのですが、その前に少し体裁を整えましょう。
次に示す3点を実施ください。
まず、ひとつめ。ボタンの文言を修正しましょう。今・・・
「ボタン1」ってなってますよね。これだとこのボタンを押下することで何が起きるのか?が直観的にわからないので、修正します。
「入力チェック」としましょう。
ボタンにマウスカーソルを合わせて右クリックしてください。
こんな風にメニューが出てくればOK。「テキストの編集」を選択しましょう。
ボタンの文言が編集モードになります。編集しましょう。
「入力チェック」にしました。フォントをほかの項目名と合わせるように「Meiryo UI」にしました。対象の文字を選択した状態で、左上のフォントを選択すると変えられます。
これで、このファイルを初めて見る保護者の方も
ああ、このボタンを押すと入力内容についてチェックをするのだろう
と直観的に理解できます。
つぎにふたつめ。シート名を変更しましょう。今・・・
「Sheet1」ってなってるんですよね・・。これ「個人情報記入票」にしましょう。文字の上でダブルクリックすると編集モードになります。
ショートカットキーでやるならAlt → H → O → R でできます。私はよく使う。
↑このようにできたらOK。
もしかするとこんなこと思ってませんかね。
プログラミングに関係ないところを教えてくれるなあ
ま、まあそうなんですが・・・汗。こういうところもめちゃくちゃ重要なんです!これ、シナリオとしては保護者の方に渡すファイルですからね。
誰が見てもわかりやすい、これめちゃくちゃ重要です。そのためにはデフォルト(初期設定/規定値)のままではいけないんです!
「デフォルト」という言葉もよく使います。システムによって最初に設定されている値のことです。
前回、エクセルファイルを初めて保存しようとしたとき、こんな↑「Book1.xlsx」という文字がファイル名欄に最初から設定されていたと思います。これもデフォルト値(ち)です。
さて、では3つめ。
今度はプログラミングです。
前回動作確認しましたけど、今って、ふりがなが入力されていたら空のメッセージボックスが出るんですよね。
(メッセージボックスのことはポップアップと呼んでもいいです。)
これを解消しましょう。
理屈としてはここまでの実装と同じです。
もしも〇〇が空っぽだったら、〇〇に△△を設定する
といった具合ですね。
それでは、以下のソースを下図のように追加してください。
'問題なしの場合
If message = "" Then
message = "入力チェックOKです。"
End If
これで動作確認してみます。
ほいキタ━━━━(゚∀゚)━━━━!!
これで意味不明なポップアップはなくなりました。
ポップアップが出るときは必ず入力エラーかチェックOKの内容です。
ここまでの3つの修正で体裁は整いました。
「ふりがな」項目のチェック処理をほかの項目にも横展開すれば入力チェックの中の
・入力漏れがないこと
は完了することができます。
では、児童の情報について、まずは同じ要領で実装していきましょう。必須マークであるアスタリスクがついている項目のみ処理を行います。
・・・が!ここでひとつ罠があるんです。
以下のソースを追加ください。性別の入力チェックです。
'性別(児童)
If Range("G4").Value = "" Then
message = "性別が選択されていません。" & vbCrLf
End If
こういう風に処理を追加するとするじゃないですか。たぶんあなたから見てもなんらおかしなところのないソースだと思う。
この状態で、「ふりがな」も「性別」も未入力・未選択状態で入力チェックを実施します。すると・・・
このように、性別についてだけメッセージに表示されます。
この入力チェックの機能は入力に不備があればその全項目をユーザに教えてあげる、という仕様です。しかし、今ふりがなと性別に不備がある状態で、性別についてだけメッセージに表示されました。
こういった、コーディング(プログラミング)をしたものの、想定と異なる結果が得られるのをバグといいます。障害とも言います。
では、「ふりがな」「性別」について正しく実装したはずなのにいったい何が起きているのでしょう。
ここで開発手法の中でも非常に重要なデバッグを学んでいただきます。
デバッグのやりかた
まずデバッグってなんだ?という話ですが、
またしてもGoogle先生に頼っちゃいました。要するにバグを治すってことなんですね。ただ私、正直驚きました。。開発現場で使われる「デバッグ」と微妙にニュアンス違うな・・・。
現場ではバグの原因を突き止める行為に対して「デバッグ」という言葉を使います。それが今から紹介するその行為(手法)です。
では原因を突き止めるというのが一体どういう行為なのか?それは端的に言っちゃうと変数の中身を追いかける、ということですね。
一緒にやってみましょう。
まず、今のソース編集画面って
こんな感じになってますかね。
ここにローカルウィンドウというものを表示させましょう。
上部メニューの「表示」から「ローカルウィンドウ」を選択します。
すると・・・
こんな風になればOK。でもソース画面が隠れちゃいましたね。右上の大画面ボタン(赤枠)を押下しましょう。
はい、これでOKです。ソース部分の大画面をもとに戻したい場合は上図右上の赤枠ボタンを押下すればできます。
さて、デバッグの下準備としてもうひとつしてほしいことがあります。めちゃくちゃ簡単です。
上図の赤丸辺りで左クリックを1回してください。
こんな風になればOKです!なにか赤いポイントが置かれましたよね。この赤い丸のことをブレークポイントといいます。
休み時間のことをブレークタイムなんて言いますが、そのブレークです。処理を小休止させるもの、と捉えてください。
それではですね、もう一度「ふりがな」と「性別」どちらも未入力・未選択の状態で、入力チェックボタンを押してみましょう。
するとすると・・・!
突如画面がソースの編集画面に切り替わったと思います。
マクロ名のところを黄色くマークしてますね。
ここで、F8キーを一度だけ押下してください。
黄色いマークが進みましたでしょうか。もしもmesseage変数のところがマークされている方はもう一度F8キーを押して前に進めてください。
この黄色くなっている行が今、実行しようとしている処理です(まだ実行はしていない)。
ローカルウィンドウの式欄にmessageと表示されていることに注意してください。これはmessage変数のことです。
それではIf文に黄色マークがある状態でさらにもう一度F8キーを押してみましょう。
はい、If文が実行されました。条件に合致しましたので、黄色マークが中に入りましたね。このとき、ローカルウィンドウの値欄の内容はまだ変更されていません。
今、黄色マークがある行の列はmessage変数に値を設定する処理です。もうだいたい想像がつきますよね。もう一度F8キーを押下してください。
はい、message変数に「ふりがなが入力されていません。」という値が設定されました。
これで先ほど実行したときは性別項目のメッセージしか表示されなかったのに、実際に処理を行っている最中では確かにmessage変数にふりがな項目へのメッセージが設定されていることが実証できました。
お楽しみはここからですよ~。ここからどうなるんだと。どうしてふりがなはメッセージに表示されなかったのかと。これは言ってしまえばふりがな殺人事件ですからね。えらいことですよ。
さて、F8キーを2回押してください。
ここです。性別項目も未選択ですからIfの中に入りました。ここで処理を進めたらどうなるんだって話なんです。
想像してください。ふりがな項目と性別項目について設定したいメッセージがmessage変数という箱を巡って喧嘩するわけです。あの箱に入るのはおれだと、わたしだと。
先に入っていたのはふりがな項目でしたが、性別項目が「わたしも入れてよ」と詰め寄るわけですよ。ふりがな項目はこの場所を死守したい・・・!
だいたい、さっきはたまたま性別項目のメッセージが表示されただけかもしれませんからね。この喧嘩に勝って。何度も実行したら違う結果が得られるかもしれませんからね。
その意味では今あなたはプログラムの中で行われる世紀の決戦の目撃者になるわけですよ。
では、いきましょう。F8キーを一度だけ押してください。
性別勝利キタ━━━━(゚∀゚)━━━━!!━━━━(゚∀゚)━━━━!!
Winner!! SE I BE TSU ~~~!!! YEAH~~~!!!!
はい、テンション上がりましたね。
今引いたり冷めたりしたあなた!野暮ですよ!
デバッグの中にも壮大な物語がある!我々プログラマーは各所で行われる戦いの立会人ですから!ちゃんと見守って一喜一憂しないと!
・・・ん、ゴホン。失礼しました。なんかデジャブ感ありましたね。
ひとまず、先に進みましょう。
ふりがな項目へのメッセージが性別項目へのメッセージに変わってしまいました。
さて、これまでのIf文は条件に一致するパターンばかりでしたので、Ifの中に入ってきました。では次はどうでしょう。
F8キーを一度押してください。
message変数が空文字かどうかをみていますが、ローカルウィンドウにある通り、message変数には既に値が設定されています。ということは・・・?
はい、F8キーを一度押しましょう。
そうですね。Ifの中には入りませんでした。当然message変数の中身が変わることもありません。
では2回F8キーを押下ください。
はい、デバッグ中でもMsgBoxの処理は実行されるので、このように画面に帰ってきます。ポップアップのOKボタンを押下してください。
またこちらに帰ってきましたね。黄色いマークが処理の最終行、End Subにあります。ここで、F8キーを一度押しましょう。これで今実装してあるマクロの処理が終わりました。
デバッグの目的は果たせましたので、ブレークポイントを外しましょう。ブレークポイントの上で左クリックしてください。
今回、ブレークポイントは処理の先頭につけましたが、例えばソースコードが100行ある場合、デバッグしたいのは70行目以降、ということもあります。
そういうときは70行目辺りにブレークポイントを付けて実行すると70行目までの処理は通常通り実行し、70行目からさきほどの手順みたいに確認することができます。
はい!デバッグおつかれさまでした~。
バグの解説
では解説していきましょうかね(∩´∀`)∩。
ふりがな項目と性別項目の件(くだり)で、実行のたびに結果が違うかもしれないじゃないか、みたいなことを言いましたが、あれは盛り上げたかっただけのウソです。失礼しました。
これもプログラミングの大切な要素で、今後学んでいく上で頭の片隅に置いておいてほしいのですが、気分や運のような要素で処理内容が変わることは絶対にありません。
プログラムは書いたとおりにだけ動きます。書いたとおりにしか動きません。
今回の場合では必ず性別項目のメッセージが代入されます。と、言いますのも・・・
'ふりがな(児童)
If Range("B4").Value = "" Then
message = "ふりがなが入力されていません。" & vbCrLf
End If
'性別(児童)
If Range("G4").Value = "" Then
message = "性別が選択されていません。" & vbCrLf
End If
こういう処理があった場合、代入は後勝ちなんですね。元から入っていた値を上書きするんです。
では、プログラミングの原則と今回のバグの原因が分かったところで、どのように修正すればいいのか?を考えてみましょう。
ふりがな項目も性別項目もmessage変数という名の箱に入れたいと。
答えはこうです。
'性別(児童)
If Range("G4").Value = "" Then
message = message & "性別が選択されていません。" & vbCrLf
End If
はい、どこが変わったかというと、代入する文の右辺です。
"性別が~"のメッセージの前にmessage & というのがついてますね。
messageはこれまでにも出てきてるmessage変数のことです。そして「&」。&は前後の値を連結する働きがあります。
つまり、今回の処理パターン(ふりがな項目と性別項目を未入力・未選択で実行)の場合・・・
message = message & "性別が選択されていません。" & vbCrLf
っていうのは
message = "ふりがなが入力されていません。" & vbCrLf & "性別が選択されていません。" & vbCrLf
と同義です。
さて、では、以下のソースを下図のように実装したところで、一度動作確認をしてみましょう。
'性別(児童)
If Range("G4").Value = "" Then
message = message & "性別が選択されていません。" & vbCrLf
End If
これで、入力チェックを押下してみます。
すーるーとっ・・・
キタ━━━━(゚∀゚)━━━━!!
はい、ふりがな項目と性別項目が未入力・未選択であることが入力チェックによって無事検出されました。これが正しい、あるべき姿です。
で、前回の時に「次回説明しまっせ」って言ったのがまだありますよね。
これ、この「& vbCrLf」。まず、&はさっき説明した通り、前の値と後ろの値を連結するものです。じゃあ「vbCrLf」はなんなんだと。このぶいびーしーあーるえるえふは。
これはね、改行文字なんです。文字通り、改行を示す文字です。注意してほしいのは改行文字はダブルクォーテーションで括っていないところ。
この改行文字の働きは試しに削除して実行してもらえると非常によくわかります。
これで実行してみますと・・・
はい。こんな風になってしまいました。ぶっちゃけ、2項目だけだとそんなに違和感ないと思います。でもこれが5項目とかあると横に伸びていくわけですよ。
こんな風・・・あれ。思ったほど横に伸びてない。
までも?読みにくいよね!汗
正しくはこのようになるわけですから(画像をクリックすると拡大表示できます)。
さてさて、ここまでの内容を頭に入れるといよいよほかの項目についても入力チェックを実装できます。
性別項目の実装をするときは罠がある~なんて言って長々とデバッグのことを説明してきましたが、ここからは本当に実装できます。
児童情報の氏名、生年月日、住所、郵便番号についても性別項目と同じ要領で実装してみましょう。
'氏名(児童)
If Range("B5").Value = "" Then
message = message & "氏名が入力されていません。" & vbCrLf
End If
'生年月日
If Range("G5").Value = "" Then
message = message & "生年月日が入力されていません。" & vbCrLf
End If
'郵便番号
If Range("C6").Value = "" Then
message = message & "郵便番号が入力されていません。" & vbCrLf
End If
'住所
If Range("B7").Value = "" Then
message = message & "住所が入力されていません。" & vbCrLf
End If
こういう処理の追加が必要で・・・
こんな風に実装できればOK。
動作確認はご自身の環境でやってみてください。さっきメッセージの改行表示のところでやったので、改めての動作確認は省略しますね。
未入力の項目のみメッセージが表示されます。
入力チェックを実装する ~初級編その3~
さて、児童の情報については実装が完了しました。
保護者の欄も同じようにやっていくのですが、少しだけ違う方法をとります。
保護者のふりがな項目はB13セルにあるので、これまで通りでいくと
'ふりがな(保護者)
If Range("B13").Value = "" Then
message = message & "ふりがなが入力されていません。" & vbCrLf
End If
こういう実装になるのですが、ここは次に学んでいただくことの布石としてセルの指定を違う方法で行います。
Range(れんじ、れいんじ)関数はセル番地を直接指定すればよかったのですが、もうひとつ、行と列の番号で指定する方法があります。
それがCells(せるず)関数です。
さっきの保護者のふりがな項目をCellsで表現するとこのようになります。
'ふりがな(保護者)
If Cells(13, 2).Value = "" Then
message = message & "ふりがなが入力されていません。" & vbCrLf
End If
If文にある比較式の左辺の内容が少し変わりましたね。しかし、指してる内容は先ほどまでと同じです。
CellsにはCells(行番号,列番号)という風に数字を指定します。B13セルは13行目の2列目ですので、13と2をカンマで区切って指定してやればそのセルの値が取得できます。
では一応動作も見てみましょう。ひとまず児童の項目はすべて埋めた状態で検証しますね。
はい、ではこのような状態で入力チェックボタンを押してみると・・・
はい、ふりがながチェックに引っ掛かりました。
「ふりがなが入力されていません。」というメッセージでは児童の方にもふりがな項目があるから混乱しないか?
というツッコミがあるかと思うのですが、ユーザの対応としては未入力の「ふりがな」項目を探すことには変わりないのでこれでヨシとさせてください。
この点は入力チェックの後続記事でちゃんと回収します。「ふりがな」がエラーのとき、児童の項目なのか保護者の項目なのかをユーザに示す方法ね。
この動作確認でわかりましたようにCells関数でも正常に動きます。
ではですね、残りの性別、児童との続柄、氏名、生年月日、電話番号、携帯番号、メールアドレスも同様に実装してみてください。
以下のソースと下図の実装イメージが出来上がりの形です。
'性別(保護者)
If Cells(13, 7).Value = "" Then
message = message & "性別が選択されていません。" & vbCrLf
End If
'児童との続柄
If Cells(13, 10).Value = "" Then
message = message & "児童との続柄が入力されていません。" & vbCrLf
End If
'氏名(保護者)
If Cells(14, 2).Value = "" Then
message = message & "氏名が入力されていません。" & vbCrLf
End If
'生年月日(保護者)
If Cells(14, 7).Value = "" Then
message = message & "生年月日が入力されていません。" & vbCrLf
End If
'電話番号
If Cells(15, 2).Value = "" Then
message = message & "電話番号が入力されていません。" & vbCrLf
End If
'携帯番号
If Cells(15, 7).Value = "" Then
message = message & "携帯番号が入力されていません。" & vbCrLf
End If
'メールアドレス
If Cells(16, 3).Value = "" Then
message = message & "メールアドレスが入力されていません。" & vbCrLf
End If
ずいぶん長くなってきました・・・!
今時点のソースを以下にダウンロードできるようにしています。不安だという方はダウンロードして答え合わせしてみてください。
さてさてさて、
・入力漏れがないこと
・正しい形式で入力されていること
・想定外の入力がないこと
の3つのうち、
・入力漏れがないこと
を実現する実装が完了しました。
入力チェックを実装する ~初級編その4~
次はひとつとばして
・想定外の入力がないこと
に取り組みますが、これはちょっと変化球なんです。というのもコーディングをしませんので。つまりソースコードを追加しません。
これはシステムを作る時の基本的な思想みたいなものなんですが、仕様やルールをシステム上に構築・実現するとき、なんでもかんでもプログラムで対応するというわけではないんですね。
プログラムを組むよりも楽で安全な手段があればそちらを採用することもあります。プログラムを組むというのはバグが生まれる可能性がついてまわることを頭の片隅に置いておいてください。
この安全な手段で実現するのが今回の「想定外の入力がないこと」にあたるわけですが、まずそもそも想定外の入力って何?という疑問があると思います。
回りくどいようだけど「想定外」があるということはそれ以前にこちらが「想定しているもの」があるわけです。例は性別項目です。
「男」か「女」の値のみを想定しています。だからもしもプログラムを組んでエラーメッセージを設定するとしたら「性別は「男」「女」のどちらかを入力してください。」とかになりますね。
でもユーザに自由に入力させた後でチェックしてエラーメッセージを出すくらいなら最初からこちらが想定している値しか入れられないようにしたらいいんです。
そこで今回使っているのが、セルの入力規則です。
性別項目はセルにカーソルを合わせると三角のプルダウンボタンが出てきます。これは事前にセルに設定したものです。
こうすることで入力チェックにかけるまでもなく、性別項目は「男」か「女」しか入力(厳密には選択)できないようにできます。プログラムを組まずにこの仕様を実現できたのでこれはこれでOKです。
賢いやり方といえましょう。
でももう少し突っ込むと
なぜ性別項目はセルに入力規則を設定したのか?
が気になる方もいるかもしれませんね。つまり「男」「女」以外に「男の子」や「女子」という入力があっても問題ないのではないかと。
いえ、これは「男」「女」のようにこちらの想定範囲内に限定されている方が後々便利なんです。後続記事で解説します。
ちなみに、エクセル自体の話ですが、セルに対する入力規則はデータタブの「データの入力規則」から設定できます。
さて、最後に
・正しい形式で入力されていること
に取り組んで入力チェックの初級編は終わりにしましょう。
入力チェックを実装する ~初級編その5~
最初に言葉の使い方について少し説明しておきましょう。
入力内容に対するいろんなチェックを総称して入力チェックといいます。まあ書いてそのままですよね。
どんなチェックを行うか?をもう少し具体的に表したい場合は○○チェックという言い回しで表現します。例えば・・・
・必須チェック:入力されているか
・形式チェック:形式が正しいか
・重複チェック:他のデータと重複していないか
・相関チェック:他の項目やデータと整合性がとれているか
などがあります。で、そうやっていくつかカテゴライズできる中の形式チェックをこの項では扱います。
説明に使うのは、郵便番号項目です。郵便番号といえば「XXX-XXXX」という形が一般的ですね。
3桁の数字、ハイフン、4桁の数字
という構成です。入力された値がこの形式に沿っているか?を検証するのが形式チェックです。なので、英字が混ざっていたり、ハイフンがない場合はエラーとします。
で、ですね。ちょっと申し訳ないんですが、この形式チェックの実装が思っていたより高度な内容でして・・・汗。
あまり頭に入れようとせず、とりあえず私の案内通りに手を動かしてください。これも理解できなくて大丈夫です。
さらさら~っと流してください。ここは、「あ、こういうこともできるのね」くらいで大丈夫です。
形式チェックには正規表現(せいきひょうげん)というものをよく使います。
正規表現とは、ある特定のパターンを持つ文字列を指定する表記法の一つ。文字列の検索や置換、抽出などを行う際の対象の指定などのために用いられる。
e-Words 正規表現 【regular expression】 RE / RegExp / regex
では、正規表現によるチェックをできるようにする設定を行います。
ソース編集画面の上部メニューからツール > 参照設定を選択してください。
すると、こんなダイアログが開いたと思います。
「参照可能なライブラリ ファイル」って言葉がありますね。ライブラリっていうのは英語で書くとLibraly、図書館です。
なにか処理を行うために必要なプログラム(部品)の集合体がその一行一行なんです。
わかりにくい単語が出てきた場合は別途調べてみるのがおすすめです(前も言ったね)。ITやプログラミングの世界はよくわからない言葉盛りだくさんですからね。
でもぶっちゃけ、調べてみてもよくわかんないってことないですか?私はよくある!そんなときにおすすめのサイトをご紹介しておきましょう。
これです。IT用語をわかりやすく解説してくれるサイト。↑ロゴをクリックするとライブラリの説明ページに飛びます。このサイト、私は公私問わずよく利用します。
というか、わからない単語を調べるとだいたいこのページがヒットする笑。
さてさて、全然意識しなくていいんだけど、ここまで書いてきたソースコードもたくさん並んでるライブラリのひとつの力を借りてるんです。
さっきのダイアログの画像に赤枠で囲ったライブラリがありますね。その左についているチェックを外そうとしてみてください。
こんな警告ポップアップが出たかと思います。このライブラリはすでに使用中なんですね。はい、余談でした。
それでは正規表現による形式チェックに必要なライブラリを追加します。
Microsoft VBScript Regular Expressions 5.5というのを頑張って探してください。探したらチェックをつけてOKボタンを押下しましょう。
ダイアログが閉じたと思います。では下準備ができたので、実装していきましょう。以下のソースを下図のように追加してください。
Dim regExp As Variant
Set regExp = CreateObject("VBScript.RegExp")
regExp.Pattern = "^\d{3}-\d{4}$"
If Not (regExp.Test(Cells(6, 3).Value)) Then
message = message & "郵便番号はXXX-XXXX形式の数値で入力してください。" & vbCrLf
End If
赤枠部分です。最後に入力内容が問題なかった場合に設定するメッセージがありますが、その手前に追加しましょう。
(このソース、全然コメントつけてませんね・・・後でご案内します汗)
それではソース解説の前に動作確認をします。
保護者の必須項目も入力した状態でやってみましょう。
まずは正常に動作するパターン・・・
はい、そうですね。「999-9999」は郵便番号の形式として正しいです。
では次に、エラーとなるパターン・・・
ハイフンを消してみました。エラーになっています。
では次、フォーマットはあってるけど、数値ではない場合・・・
これもエラーですね。
動作を確認できたところで、ソースを解説しましょう。
先ほども貼り付けましたが・・・
Dim regExp As Variant
Set regExp = CreateObject("VBScript.RegExp")
regExp.Pattern = "^\d{3}-\d{4}$"
If Not (regExp.Test(Cells(6, 3).Value)) Then
message = message & "郵便番号はXXX-XXXX形式の数値で入力してください。" & vbCrLf
End If
こんなソースコードを追加いただいたんでしたね。1行ずつみていきます!
Dim regExp As Variant
まずはこれ。前回もmessage変数の宣言として似たようなものがありましたね。今回も変数の宣言としては同じです。違うのは変数名とデータ型のみ。
Dim 変数名 As データ型 ←変数宣言の構文です。
まず、変数名「reqExp」。突然「reqExp」って言われても意味不明ですよね。「message」のときはメッセージだから直観的にわかったけども。
reqExpというのは・・・
正規表現の英訳を略したものなんですね。つまり正規表現を管理する変数です。で、こんなことを思う人がいるかもしれません。
「reqExp」の最初の「r」が小文字で途中の「E」が大文字なのはどうして?
う~ん、いい質問!でもここでは答えません。まだ覚えなくていい!後続記事では必ず触れるから楽しみにしててください。
変数名の次はデータ型も初出ですね。
Dim regExp As Variant
Variantと書いてバリアント型。Variantはどんなタイプのデータでも格納できてしまうちょっと特殊なやつです。すごいやつなんです。えっへん。
次、
Set regExp = CreateObject("VBScript.RegExp")
これは完全に初めて見るタイプですね・・・。新種のソースコードだぞ・・。でも基本は同じです。これも右辺を左辺に代入しています。
先頭の「Set」は決まり文句だと思ってください。「オブジェクト」と呼ばれるものを代入するときはSetを使います。ここは後続記事でも触れるので今は「へ~(*´з`)」くらいに流してもらえばいいです。
で、問題の右辺ですよ。「CreateObject("VBScript.RegExp")」これ。
「VBScript」ってどこかでみた文字列ですよね。そう、先ほど追加したライブラリです。
これね。
この正規表現に関するいろんな機能(処理)を持ったアイテム(Object)を実体化(Create)してreqExp変数に代入している、という風に理解してください。正規表現オブジェクトをregExpに格納しています。
(「代入」も「格納」も同じ意味として捉えていただいて大丈夫)
Set regExp = CreateObject("VBScript.RegExp")
これで正規表現に関する処理はこのreqExp変数が一手に引き受けてくれます。
例えば・・・
reqExpさ~ん。郵便番号の形式チェックをしたいよぉ~う。
reqExp「ほう、どんな形式を許容するんだい?」
え、えーと・・・XXX-XXXXで数値のみを受け付けるようにしたいです!
reqExp「あいよ!引き受けやした!」
・・・というのをやっているのが、次に出てくる
regExp.Pattern = "^\d{3}-\d{4}$"
これ。
でも見たところ、意味不明ですよね。結構内容が高度だって言ったのはこういうところなんですよ。さっきのライブラリ追加するとこなんかもだけど。
まず、reqExp変数は正規表現に関する処理をするためのいろんな道具や機能をもっていると先ほど言いました。その一つが「Pattern」(という変数)。
regExp.Pattern = "^\d{3}-\d{4}$"
これを言葉で表現するとreqExp変数に格納された正規表現オブジェクトがもつ「Pattern」という箱(変数)に「"^\d{3}-\d{4}$"」という文字列を代入している、ということになります。
じゃあ「"^\d{3}-\d{4}$"」はなんなんだと。これこそがね、正規表現なんです。
ざっくり解説すると・・・「\d」は数値を表しています。「{3}」は前の文字(数値)を3回繰り返す、という意味。ここまでで、3桁の数値です。
次に「-」ハイフン。これは見たまんまハイフンです。
そしてもう一度「\d」が出てきますね。さっきと同じ数値です。さらに「{4}」で前の文字(数値)を4回繰り返す、ということ。
正規表現は(ほんとはよくないんだけど)正しく出来上がってる内容を紹介しているサイトから(よく理解もしないで)拝借することが現場の人間でもよくあります。マネしないでね。いや、マネするしかないよ。
なんか一気に難しくなった感ありますね・・・でもいやにならないで!初心者向けに丁寧に解説するという性質上、説明はしてるけど話半分に聞いておけばいいから!なんなら飛ばしてもいいから!くどいようだけど!
さて、話を戻して次の処理を見てみましょう。
If Not (regExp.Test(Cells(6, 3).Value)) Then
message = message & "郵便番号はXXX-XXXX形式の数値で入力してください。" & vbCrLf
End If
はい、出ました If文。
ここは雰囲気でわかると思うけど、Cells(6,3).valueの内容、すなわち郵便番号の入力内容が先ほど指定した正規表現にマッチしているかどうかをチェックしています。
つまり、Cells(6,3).valueが「123-4567」という値を取得していたとしたら・・・
If Not (regExp.Test("123-4567")) Then
message = message & "郵便番号はXXX-XXXX形式の数値で入力してください。" & vbCrLf
End If
というのと同義です。
書き方は微妙に異なれど、こういう処理は各プログラミング言語に存在します。もちろんPHPにも。
reqExpがもってる「Test」という機能(関数)は指定された文字列の内容が「Pattern」にもってる正規表現に一致するかどうかを検証する、という処理を行います。指定された文字列とは今回で言うと郵便番号の入力値のことです。
ここで一点注意があります!今、さらっと
「Pattern」にもってる正規表現に一致するかどうかを検証する
といいました。If構文では条件に合致したらIf文の中の処理に入るんでしたよね。
で、正規表現に一致するかどうかを検証する、ということは一致したらエラーメッセージをmessage変数に設定する処理に入ってしまうんです。
いや、そうじゃないと。一致していたらOKなわけだから一致しなかったときにIfの中に入りたいんです。
そこでやっているのが・・・
If Not (regExp.Test(Cells(6, 3).Value)) Then
message = message & "郵便番号はXXX-XXXX形式の数値で入力してください。" & vbCrLf
End If
Ifの横にあるNot()ですね。Not(条件式)を使うと結果を反転させることができます。
これで、正規表現に一致しなかったときにIfの中に入るようにしています。
はい、解説はここまで。
でも最後にもうひとつだけ・・・!
試しに郵便番号の項目を空っぽにして入力チェックを実行してみてほしい。
はい、ソースコードに書いたとおりに動きましたね。エラーメッセージが2つ出ていますが、どちらも正しいです。
・・・でもちょっとツッコミどころありません?
入力されてないのはわかるけど、入力されていない項目に対して形式もなにもないでしょう、と。
そうです。形式に関するエラーメッセージは入力されているという前提がある上で検証されるべきです。
ですので、先ほど実装いただいたソース・・・
Dim regExp As Variant
Set regExp = CreateObject("VBScript.RegExp")
regExp.Pattern = "^\d{3}-\d{4}$"
If Not (regExp.Test(Cells(6, 3).Value)) Then
message = message & "郵便番号はXXX-XXXX形式の数値で入力してください。" & vbCrLf
End If
これをまるっと切り取りいただきまして・・・
Else
'正規表現オブジェクト
Dim regExp As Variant
'正規表現オブジェクトの実体化
Set regExp = CreateObject("VBScript.RegExp")
'正規表現パターンの設定
regExp.Pattern = "^\d{3}-\d{4}$"
'郵便番号形式チェック
If Not (regExp.Test(Cells(6, 3).Value)) Then
message = message & "郵便番号はXXX-XXXX形式の数値で入力してください。" & vbCrLf
End If
この↑ソースを下図のように追加してください。コメント追加しました。コメントは一目見ただけでは何やってるかわからない処理なんかに書くと便利です。
赤枠部分です。
ここにきてIf構文の新要素がでてきました。Else(えるす)です。
If 条件式A Then
条件式Aを満たした場合の処理
Else
条件式Aを満たさなかった場合の処理
End If
こういうことですね。郵便番号の形式チェックは郵便番号に入力がある時だけ行いたいという事情がありました。
ですので、郵便番号の必須チェックがOKだったときだけ形式チェックを行うようにしました。Elseはよく使うので、これからも出てきます。
はい!入力チェックの第一弾としてはこれで完成です!
次は第二弾いきましょう!入力チェック機能とのお付き合いはもう少し続きますが、我慢してください・・・!プログラミングの基礎的内容な上にいろんな要素を教えやすいんです。
今回もCtrl + Sで上書き保存しておいてください。手を動かすのはここまでです!
あとがき・ふりかえり
まずはお疲れさまでした。今回はボリューム多めになりましたね笑。
今回のあとがきでは以下の5つのことを伝えさせてください。
・ソース編集時の自動補完
・変数名の重要性
・テストデータのこと
・記事中のソースの色について
・デバッグの補足
-- -- --
・ソース編集時の自動補完
本文中でいろんなソースをご紹介していますが、ひとつひとつ手でタイピングしていただいているでしょうか。コピー&ペーストでももちろんOKです。
ソースコードには結構小文字・大文字が混在していてぶっちゃけ打つの面倒に思うときありませんか?いや、あっていいんですよ。
実はExcelVBAには便利な機能が標準装備されていまして。
例えばもうすっかりおなじみの「message」って変数あるじゃないですか。
これ、今ソースの編集画面でためしにやってほしいんですけど、先頭の「me」まで打ったらそこでCtrl + スペースキー押してもらえますか。
するとじゃじゃーん!!残りの「ssage」を勝手に入れてくれます!便利~~~!!!自動補完~~!!
ではもうひとつ。ソース上のどこでもいいから「r」と打ってください。そしてCtrl + スペースキーを押下しましょう。
こんな↑風になればOK。「r」から始まる変数や関数の候補を出してくれるんです(関数のことは後続記事で説明します)。
じゃあこの状態でさらに「e」と打ってみましょう。
・・・なんと!「re」で始まるものを優先的に表示してくれている!
ありがたいですね~(∩´∀`)∩。プログラミングに慣れてくるといろんな関数が出てきますし、プログラム中に使用する変数の数も結構増えたりします。そんなときにいちいち全部を覚えてはいられません。
だから「あの~・・・reで始まるアレなんだったっけ・・・」というところまで思い出せていたらあとはCtrl + スペースキーを押しちゃえばいいんです。あとはプルダウンから選択するだけなのでね。
あと細かいことで申し訳ないんだけど、上図のようなプルダウンから選択するとき、エンターキーを使うと改行してしまいます。でもこれを使うときは選択したときに改行したくないことが多いです。
そういうときはTabキーで選択しましょう。すると選択後にその行にカーソルがとどまっていてくれます。
ちなみに、大文字小文字が混在している変数名・関数名でも全部小文字で入力してカーソルを離れたら大文字小文字の調整は自動的にやってくれます。
だからIfの「I」もRangeの「R」もCellsの「C」も入力時は全部小文字でOKです。カーソルを違う行に移したら勝手に補完してくれますので。
-- -- --
・変数名の重要性
次に変数名の重要性についてです。
ここまで実装いただいたソースコード中には2つの変数が出てきました。
messageとexgReqです。これ、私が言ったとおりに実装いただいてるだけなのでなにも思わないと思いますが、変数にどんな名前をつけるか?はめちゃくちゃ重要です。
messageだったら「なにかメッセージを格納するものなのだろう」と推測できますし、exgReqも「正規表現に関する処理をするのだろう」ということがわかります。
これは平たく言うと美しいソースコードを書くためですね。コーディングのお作法の話です。
実際に変数名の重要性に気付くのは変数名が適当なせいでなにか苦労させられた時だと思います。なのでなかなかその機会はないかもしれませんが頭の片隅に置いておいてください。
そして処理の内容と変数名が一致するように心がけましょう。
-- -- --
・テストデータのこと
次に、テストデータについてです。
今回、私は説明にあたって以下のようにデータを設定しました。
まあいかにもサンプルという感じですよね。
(あ、ごめんなさい汗 ふりがなの花子が漢字になってる!)
プログラミングの個人学習はやはりモチベーションの維持が大切ですので、こういう動作確認用のデータでも身近な情報を用意した方が愛着が湧くという人もいるでしょう。というか私がそう。
ですので、外部に出したりしない限りはガチのあなたの個人情報を書いてもらっても大丈夫です。あなたのパソコン内だけの話なのでね。(とはいえセキュリティには気を付けて。ウイルス感染とか)
結構テストに使うデータって「ああああああ」とか「TEST」にしがちですけど、実際のデータを使わないと発見できないバグもたまにあったりしますからね。
何より、マジっぽいデータを使うと臨場感が出ます!
-- -- --
・記事中のソースの色について
次に記事中のソースの色についてです。
Else
'正規表現オブジェクト
Dim regExp As Variant
'正規表現オブジェクトの実体化
Set regExp = CreateObject("VBScript.RegExp")
'正規表現パターンの設定
regExp.Pattern = "^\d{3}-\d{4}$"
'郵便番号形式チェック
If Not (regExp.Test(Cells(6, 3).Value)) Then
message = message & "郵便番号はXXX-XXXX形式の数値で入力してください。" & vbCrLf
End If
さきほども出てきたこのソース。ソースによって、色がついているじゃないですか。これnoteの仕様で私自身にはなんの意図もないので、気にしないでください。
-- -- --
・デバッグの補足
デバッグの説明の時に、ネットで出てきたデバッグの説明文が開発現場のニュアンスと微妙に違うんだよな、という話をしました。ここ、補足させてください。
まあプログラミング始めたばかりの人には関係ないような話ですけどね。読み物として。
↑ここでは、デバッグは1:バグの発見、2:バグの修正と定義されています。
最初に注意しておきたいんだけど、ゲーム開発なんかにはたしかにデバッガーと呼ばれるバグ発見部隊的な人やツール・ソフトがあります。なので、その文脈で言うと間違いではありません。
が、開発の現場ではデバッグを見つける行為はテストとか動作確認って言います。ありふれた言葉。
で、バグが見つかったらじゃあデバッグしよう(原因を見つけよう)となります。
で、デバッグで原因が判明したらじゃあ修正しよう、という流れです。
どうして開発現場のニュアンスでは「デバッグ」の中に修正まで含まれていないかというとバグに対する修正方針って結構ピンキリなんですよ。
凡ミスだったら開発者自身で対応できますが、バグの内容によっては設計の時点で考慮が漏れている、なんてこともありますのでね。だから原因がわかったら上の人間に相談するってこともよくあります。
そんななので、これ以降の記事でもデバッグという言葉が出てきたらバグの原因を探す行為として捉えてください。よろしくお願いします。
以上!
おわりに
おわりでーっす!
デバッグよりもループ処理メインでやるつもりだったのですが、そこまでいけませんでした笑。まあゆっくりやっていきましょう。
次回はループをやります!繰り返し処理!
ではでは、美味しいもの食べて脳みそ休めてあげてください!
今回もありがとうございました!
次回へ続く!
この記事が気に入ったらサポートをしてみませんか?