【VBA基礎⑦】UserFormの使い方

皆さんはVBAのユーザーフォームを知っていますか?ユーザーフォームはインターフェースを簡単に構築できる機能として、多くの場面で役立ちます。本記事では、ユーザーフォームの作成方法や、基本的な使い方について詳しくご紹介します。ユーザーフォームを使ったプロジェクト管理に関心がある方は、ぜひ参考にしてみてくださいね!

この記事はVBAの基礎シリーズです。他の記事は以下のリンクからご覧いただけます!

UserFormとは?

ユーザーフォームはVBAで設計できるユーザーインターフェースです。ユーザーから情報を受け取ってデータベースを作成・呼び出しをしたり、アプリの操作画面として利用するなど、自由な使い方ができます。ユーザーフォームを使用することで、通常のワークシート上ではできない作業が可能になるため、操作性が大きく向上します。

一例としてユーザーフォームで簡単なクイズアプリを作ってみました。ユーザーフォームを起動すると問題文と選択肢が表示され、回答を選択するとメッセージがポップアップし、スコアが集計されます。

ユーザーフォームがどのようなものか分かったところで、実際の作り方を説明してきます。

UserFormを作成する手順

ユーザーフォームを作成するためには順番に「設計」「コーディング」「表示」の3つの作業が必要になります。以下に詳細を記載していきます。

設計

ユーザーフォームの設計とは、ユーザーフォームの操作画面をデザインすることです。上の例で言えば、問題文を表示する「ラベル」や選択肢の「オプションボタン」、次の問題に進むための「コマンドボタン」の配置や文字の表示を設定することを言います。

まずはユーザーフォームを挿入します。VBAの管理画面を開き、「挿入タブ」の「ユーザーフォーム」を選択します。するとユーザーフォームが挿入されます。

ユーザーフォームを挿入すると、一緒にツールボックスが表示されます。ユーザーフォームを設計するための「ラベル」や「コマンドボタン」は、このツールボックスのコントロールから選択して配置していきます。

ツールボックスが表示されない場合は、「表示」タブの「ツールボックス」を選択して表示します。

続いて、ツールボックスのコントロールの種類について詳しく解説していきます。

「ラベル」は、ユーザーに情報を伝えるためのテキスト表示用のコントロールです。ラベルはテキストボックスやボタンの近くに配置し、入力項目の目的や、その内容を分かりやすく説明するために使用します。例えば、ユーザーフォームで年齢や名前を入力させたい場合、テキストボックスの近くに「年齢」や「名前」と記載したラベルを配置することで、ユーザーにとって分かりやすくなります。

ラベルを挿入するときは、ツールボックスの「ラベル」を選択し、ユーザーフォーム上でドラッグすることで配置できます。

ツールボックスからコントロールを配置する際は、いずれもユーザーフォーム上でドラッグして配置します。

「テキストボックス」は、ユーザーからの入力を受け取るためのコントロールです。例えば、ユーザーが年齢や名前を入力するための入力欄として、ラベルの近くに配置します。

テキストボックスを挿入するときは、ツールボックスの「テキストボックス」を選択します。テキストボックスを挿入して、ユーザーフォームを起動すると、テキストボックスに自由に文字を入力することができます。

「コマンドボタン」は、ユーザーの操作によってなんらかの処理を起動するためのコントロールです。

コマンドボタンを挿入するときは、ツールボックスの「コマンドボタン」を選択します。コマンドボタンを挿入して、ユーザーフォームを起動すると、ボタンとしてクリックすることができます。データの送信や計算の実行など、何らかの処理をクリック動作と結び付けておくことでその処理をユーザーフォーム上から実行することができます。

「リストボックス」は、ユーザーが複数の選択肢から項目を選ぶためのコントロールです。

リストボックスを挿入するときは、ツールボックスの「リストボックス」を選択します。リストボックスを挿入して、マクロであらかじめリストに表示する項目を設定し、ユーザーフォームを起動すると、リストとして項目を選択することができます。

「コンボボックス」は、リストボックスと同様、ユーザーが複数の選択肢から項目を選ぶためのコントロールです。リストボックスとの相違点はドロップダウンリスト形式で表示されることです。

コンボボックスを挿入するときは、ツールボックスの「コンボボックス」を選択します。コンボボックスを挿入して、マクロであらかじめリストに表示する項目を設定し、ユーザーフォームを起動すると、ドロップダウンから1項目を選択することができます。

「チェックボックス」は、ユーザーが項目を選択または選択解除できるコントロールです。複数の項目からのユーザーが自由に選択したり、選択された条件に応じた処理を行う場合に使用します。

チェックボックスを挿入するときは、ツールボックスの「チェックボックス」を選択します。チェックボックスを挿入して、ユーザーフォームを起動すると、チェックボックスを自由に複数選択することができます。

「オプションボタン」は、複数の選択肢の中から1つだけを選択するためのコントロールです。オプションボタンは、ユーザーが1つ選択肢を選んだ場合、他の選択肢は自動的に無効化されます。

オプションボタンを挿入するときは、ツールボックスの「オプションボタン」を選択します。オプションボタンを挿入して、ユーザーフォームを起動すると、任意のボタンを選ぶことができます。

「イメージ」は、画像を表示するためのコントロールです。これにより、ユーザーインターフェースを視覚的に豊にしたり、情報を視覚的に伝えることができます。例えば、商品やサービスのロゴや画像を表示する時に使用されます。

イメージを挿入するときは、ツールボックスの「イメージ」を選択します。イメージを挿入して、あらかじめマクロで表示する写真を設定し、ユーザーフォームを起動すると、設定した写真を表示することができます。

ちなみにVBAがサポートしている形式はBMPJPEGGIF などです。PNG形式はサポートされていないので、注意しましょう。

コーディング

設計の手順と概要を掴んだところで、次はユーザーフォームのコーディングについて説明します。コーディングとは配置したそれぞれのコントロールの動作に必要なマクロを記述することです。

例として、上記で説明したいくつかのコントロールを使用して最初に紹介したクイズアプリの作り方を解説してみます。

まずは上記で説明したように、ユーザーフォームを設計します。ユーザーフォームを挿入し、以下のコントロールを配置します。

ラベル×2 ⇒ 問題文とスコアの表示用

オプションボタン×4 ⇒ 回答の選択肢の表示用

コマンドボタン×1 ⇒ 次の問題に進む用

コントロールの処理を記述するマクロは、ユーザーフォーム専用のモジュール内に記述します。ユーザーフォーム用のモジュールを表示するには、プロジェクトウィンドウから目的のUserFormを選択し、右クリックから「コードの表示」を選択すると、コードウィンドウが表示されます。

実際にコードを記述していきます。まずは必要な変数を宣言していきます。今回はモジュールレベル変数を使用します。

Option Explicit

Dim questionIndex As Integer
Dim score As Integer
Dim questions(1 To 3) As String
Dim options(1 To 3, 1 To 4) As String
Dim correctAnswers(1 To 3) As Integer

モジュールレベル変数とは宣言セクション(モジュール内の最上位の位置)で宣言した変数です。モジュールレベル変数は宣言したモジュール内の全てのプロシージャで使用できます。

各変数は以下の目的で使用します。

questionIndex ・・・問題番号を振る変数
score ・・・スコアを代入する変数
questions(1 To 3) ・・・問題文を代入する配列
options(1 To 3, 1 To 4)・・・回答の選択肢を代入する配列
correctAnswers(1 To 3)・・・正解の選択肢を代入する配列

配列「options」は2次元配列を使用しています。2次元配列は変数名( 数値 , 数値 )のように宣言し、配列のインデックスを1-1 , 1-2・・2-1 , 2-2 ,・・のような行列の形式で管理することができます。

次に問題文と選択肢を表示できるように、あらかじめ設定しておきます。初期設定にはユーザーフォームのイベントの1つである「Initialize」を使用します。「Initialize」は、ユーザーフォーム起動時に記述した処理が自動で実行されるイベントです。

コードウィンドウの左上にオブジェクトボックス、右上にプロシージャボックスがあります。オブジェクトボックスで選んだオブジェクトに対して、プロシージャボックスで使用可能なイベントを選択することができます。オブジェクトボックスは「UserForm」を選択、プロシージャボックスは「Initialize」イベントを選択します。

プロシージャが挿入されたら以下のコードを記述します。それぞれの変数に自由に問題文と選択肢、正答の番号を代入していきます。必要な情報を入力したら、問題番号の変数「questionIndex」に1を、スコアの変数「score」に0を代入して、プロシージャ「LoadQuestion」を呼び出して次の処理に移ります。

Private Sub UserForm_Initialize()
 questions(1) = "Q1: 60dB + 60dB はいくつ?"
 options(1, 1) = "63dB"
 options(1, 2) = "66dB"
 options(1, 3) = "90dB"
 options(1, 4) = "120dB"
 correctAnswers(1) = 1

 questions(2) = "Q2: 3 □ 4 1 5 9 2 6 5 □に入る数字は?"
 options(2, 1) = "5"
 options(2, 2) = "2"
 options(2, 3) = "1"
 options(2, 4) = "0"
 correctAnswers(2) = 3

 questions(3) = "日本人で9人目となるプリツカー賞を2024年に受賞したのは?"
 options(3, 1) = "丹下健三"
 options(3, 2) = "山本理顕"
 options(3, 3) = "安藤忠雄"
 options(3, 4) = "坂茂"
 correctAnswers(3) = 2

 questionIndex = 1
 score = 0
 LoadQuestion

End Sub

続いて、呼び出し先のプロシージャ「LoadQuestion」を作成していきます。

Private Sub LoadQuestion()
 Label1.Caption = questions(questionIndex)
 OptionButton1.Caption = options(questionIndex, 1)
 OptionButton2.Caption = options(questionIndex, 2)
 OptionButton3.Caption = options(questionIndex, 3)
 OptionButton4.Caption = options(questionIndex, 4)
 OptionButton1.Value = False
 OptionButton2.Value = False
 OptionButton3.Value = False
 OptionButton4.Value = False
 Label2.Caption = "スコア: " & score
End Sub

まずラベルに問題文を代入します。「Label1」が問題文の表示用に配置したラベルのオブジェクトです。「.Caption」はコントロールに表示するテキストを設定するプロパティです。ここに変数「 questions」を代入します。questionIndex=1ですので、1番目の問題文がラベルに代入された状態になります。

次にオプションボタンに選択肢を表示します。「OptionButton1~4」が配置したオプションボタンのオブジェクトです。ここに変数「options」を代入します。questionIndex=1ですので、1番目の問題文の選択肢がオプションボタンに代入された状態になります。

続いて、オプションボタンのオブジェクトの「.Value」プロパティを「False」に設定します。これにより、オプションボタンのチェックが外れた状態になるので、次の問題に進む際にオプションボタンのチェックが外された状態で表示されます。

最後にスコア表示用のラベルに変数「score」を「Label2」へ代入することでスコアを表示します。

ちなみにコントロールのキャプションやサイズ、表示位置などは、コントロールをクリックすると表示されるプロパティから設定できます。

上記のまでの作業で、ユーザーフォームを立ち上げた時に、最初の問題文と選択肢が表示された状態になるので、次はコマンドボタンをクリックすることで、選択した回答の答え合わせと次の問題に進むためのコードを記述します。

コマンドボタンの設定にはイベントの「Click」イベントを利用します。コマンドボタンのクリックイベントはコマンドボタンがクリックされた時に記述した処理が実行されます。オブジェクトボックスは対象の「CommandButton」を選択、プロシージャボックスは「Click」を選択して、イベントプロシージャを挿入します。

プロシージャを挿入したら以下のコードを記述します。

Private Sub CommandButton1_Click()
 Dim selectedAnswer As Integer


  If OptionButton1.Value = True Then
   selectedAnswer = 1
  ElseIf OptionButton2.Value = True Then
   selectedAnswer = 2
  ElseIf OptionButton3.Value = True Then
   selectedAnswer = 3
  ElseIf OptionButton4.Value = True Then
   selectedAnswer = 4
  Else
   MsgBox "選択肢を選んでください。"
   Exit Sub
  End If

  If selectedAnswer = correctAnswers(questionIndex) Then
     score = score + 1
     MsgBox "正解です!"
  Else
     MsgBox "不正解です。"
  End If

  questionIndex = questionIndex + 1

  If questionIndex <= UBound(questions) Then
     LoadQuestion
  Else
     MsgBox "クイズ終了!あなたのスコアは " & score & " 点です。"
     Unload Me
  End If

End Sub

ユーザーが選んだ選択肢の番号を代入するための変数「selectedAnswer 」を宣言しておきます。

次にIfステートメントを利用してユーザーがどの選択肢を選んだかを調べ、選択肢の番号を変数「selectedAnswer 」に代入します。
選択肢を選ばずにコマンドボタンをクリックした場合、「選択肢を選んでください。」というメッセージを表示して処理を終了させるようにExitステートメントを記述しておきます。

選択肢が選ばれていたら、ユーザーの回答と正答が合っているかをIfステートメントで調べます。もし合っていればスコアを1点加算し「正解です!」と表示、間違っていれば「不正解です。」と表示します。

一連の確認が終了したら、次の問題に進むために変数「questionIndex」を+1しておきます。

最後に今の問題番号が何番かを調べ、最後の問題でなければ再度「LoadQuestion」プロシージャを読み込む、最後の問題ならば、スコアを表示してユーザーフォームを終了するコードを記述します。

UBound関数は配列の最大値を返すことができるので、引数に配列「questions」をとり、If文を使用して問題番号の変数「questionIndex」と比較することで問題が最後まで表示されたかを調べています。関数についてはVBA基礎⑤で解説しているので、ぜひそちらも読んでみてください!

表示

設計とコーディングが完了したら最後にユーザーフォームを表示させるコードを記述します。UserFormを表示するのは以下のように「Show」メソッドを使用します。以下のマクロは標準モジュール内に記載しています。

Sub ShowQuiz()
 UserForm1.Show
End Sub

ユーザーフォームの番号は、ユーザーフォームを挿入した順に番号が振られます。ユーザーフォームを選択して、プロパティの「オブジェクト名」を確認すると、そのユーザーフォームのオブジェクト名を調べられます。このオブジェクト名を変更すると、ユーザーフォーム表示用のマクロも修正が必要になるので注意してください。

まとめ

完成したクイズアプリがこちらです。

今回はユーザーフォームを使用して簡単なクイズアプリを作成しました。この他にもユーザーフォームは様々な使い方ができるので、この記事を参考にぜひ使用してみてくださいね!それではまた。