🚀The world's best VBA AI has evolved. ExcelMaster is now an autonomous Agent.Read more →
Back to Blog

Excel VBA の Frame — OptionButton のグループ化と、コントロールのスコープ

|

Excel VBA の Frame — OptionButton のグループ化と、コントロールのスコープ

TL;DR — Frame は装飾ではなく、コンテナーです。ラベル付きの枠線はその中でいちばん小さな部分にすぎませ ん — Frame は中のコントロールを 所有 しています。その所有関係のおかげで、 オプションボタン の一組をグループとして排他的にできます — フォームに直接置かれた オプションボタンはすべて一つのグループになるので、選べるのは常にどれか一つだけです。Frame は自分自身の Controls サブコレクションと、自分自身の .Enabled、.Visible も持っているので、セクション全体を一度に オン・オフできます。

' 独立した二つの選択には、二つの Frame が必要。
' fraSize の中の OptionButton どうしは互いに排他的で、
' fraColour の中の OptionButton は別のグループ。
Private Sub UserForm_Initialize()
    fraSize.Caption = "Size"
    fraColour.Caption = "Colour"
    optSmall.Value = True        ' Frame ごとに一つの既定値
    optRed.Value = True
End Sub

Frame は、ほかの コントロールのために追加する唯一の UserForm コントロールです。単独ではほとんど何もしま せん。その目的はグループを収めることであり、そのコンテナーとしての役割がコントロール一家を完成させます。ほか の何もかもと同じようにフォームの Controls コレクション を通して到達し、 オプションボタンのグループ化ルール が実際に住んでいる場所であり、フォームの一区画を 単位としてスコープし切り替える方法です。フォームに二組のラジオボタンを置いて、一方を選んだらもう一方の選択が 解けてしまった経験があるなら、このコントロールがその直し方です。

この記事で学べること

  • Frame が単なる枠線ではなく、自分のコントロールを所有するコンテナーである理由
  • Frame が存在する理由であるルール:グループごとにオプションボタンを排他的にする
  • GroupName という代替手段と、それを選ぶべき場面
  • Frame が自分自身の Controls サブコレクションを持つこと
  • Frame の .Enabled と .Visible でセクション全体を切り替える方法
  • Parent チェーンと、それがコントロールへの到達方法を変える理由

考え方の軸:Frame は装飾ではなくコンテナー

Frame をキャプション付きの飾りの箱だと見なしたくなりますが、それは本当は 親 です。その中に描いたコント ロールは、フォームではなく Frame に属します。この一つの関係 — Frame が子を所有する — が、Frame の有用さのす べての源です。Frame を動かせば子も動きます。Frame を無効化すれば子もグレーアウトします。そして Frame の中の オプションボタンの一群は、自分たちの間だけで競い合います。目に見える枠線は、所有権の境界線が見えている端にす ぎません。

Frame が存在する理由:オプションボタンのグループ化

これが本題です。OptionButton(ラジオボタン)は 自分のコンテナーの中で 互いに排他 的です。六つのオプションボタンをフォームに直接置くと、それらは一つのコンテナー — フォーム — を共有します。だ から、たとえ二つの別々の質問のつもりでも、どれか一つを選ぶとほかの五つが解除されてしまいます。

' 間違い:素のフォームに六つのオプションボタン = 一つのグループ。
' optRed を選ぶと optSmall が解除される。ユーザーはサイズと色の両方を選べない。

各質問をそれぞれ自分の Frame に入れれば、それぞれが独立したグループになります。

' 正解:fraSize に三つのサイズ選択肢、fraColour に三つの色選択肢。
' これでユーザーは、独立してサイズを一つと色を一つ選べる。

Frame とは、すなわちグループです。これは気の利いたおまけではなく、フォーム上に複数組のラジオボタンを置く唯 一のきれいな方法です。(CheckBox はこの方法でグループ化されることはなく、それぞれが独立しています — これ がまさに CheckBox との違いです。)

GroupName という代替手段と、それを選ぶべき場面

オプションボタンをグループ化する方法がもう一つあります。同じ GroupName 文字列を与えることです。 GroupName を共有するボタンは、周りに Frame がなくても排他的になります。

optCash.GroupName = "Payment"
optCard.GroupName = "Payment"     ' optCash と排他的、Frame は不要

グループ化が 見た目にも 必要なとき — 選択肢が仲間だとユーザーに見えるべきで、単位として有効化や非表示をし たいとき — は Frame を選びましょう。目に見えるコンテナーなしで排他性だけが必要なとき、あるいはレイアウト上 Frame が扱いにくいときは GroupName に手を伸ばします。Frame のほうが既定として優れているのは、フォームを読 む次の人にグループ化が一目でわかるからです。

Frame は自分自身の Controls コレクションを持つ

Frame は子を所有しているので、自分自身の Controls コレクション — フォームのコレクションの部分集合 — を持 っています。おかげで、一つのセクションの中のコントロールだけをループできます。

Dim ctl As MSForms.Control
For Each ctl In fraSize.Controls        ' fraSize の中のコントロールだけ
    If TypeOf ctl Is MSForms.OptionButton Then
        If ctl.Value Then MsgBox "Size chosen: " & ctl.Caption
    End If
Next ctl

これは Me.Controls を Frame にスコープしたものです。フォームの残りに触れずに、 この グループでどのオプションが選ばれているかを読み取る方法です — Frame のコントロールをループして、 .Value が True である一つのオプションボタンを見つけます。

Enabled と Visible でセクション全体を切り替える

Frame の .Enabled や .Visible を設定すれば、すべての子がそれに従います。

fraShipping.Enabled = chkShip.Value      ' 配送セクション全体をグレーアウト
fraAdvanced.Visible = False              ' 必要になるまで詳細設定を隠す

コントロールをループする代わりに、一行でセクション全体 — 住所、支払い、詳細設定 — を無効化したり隠したりでき ます。これがコンテナーモデルの日々の見返りです。Frame はグループを単位として扱うための取っ手なのです。

Parent チェーン:コントロールの本当の親

所有関係は血筋を変えます。Frame の中のコントロールは、フォームではなくその Frame を Parent として持ちます。

MsgBox optSmall.Parent.Name     ' "fraSize" になる。フォームの名前ではない

これで人がつまずく結果が二つあります。まず、コントロールの .Left と .Top はフォームではなく Frame を基 準に測られるので、コントロールを Frame とフォームの間で移動すると、着地する位置がずれます。次に、Frame に入 ったコントロールは Frame を通して到達するもので、フォーム自身の Controls のトップレベルの項目としてではあ りません — だから、トップレベルにあると期待したフォームレベルのループはそれを見落とします。コントロールの位 置がおかしい、あるいは探した場所に見つからないと感じたら、その Parent が Frame かどうかを確かめましょう。

判断のしどころ:Frame が場を得るのはいつか

Frame は安上がりですが、タダではありません — 親チェーンとコントロールへの到達方法に一段を加えます。実際の仕 事をするときだけ追加しましょう:複数組のオプションボタンがある、あるいは単位として有効化・非表示・読み取りを したいセクションがある、というときです。見た目のためだけにすべてのラベルや箱を Frame で包んでは いけません — それは親チェーンを深くするだけで、フォームレベルの Controls ループが、トップレベルにあると期待したコント ロールを見落とす原因になります。経験則はこうです:Frame は ユーザーが一つのものとして考えるグループ に対応 すべきです — いくつかの答えを持つ一つの質問、一緒にオンになるセクション。何もグループ化していないなら、それは ただの枠線にすぎず、それなら副作用のない素のラベルで十分です。

ExcelMaster の活用

Frame にまつわる定番のバグは、フォームをテストするまで目に見えません。Frame に入れなかったせいで互いに争う 二組のラジオボタン、あるいは忘れていた Frame が親になっているせいで間違った位置を報告するコントロール。レイ アウトの問題に見えて、実は所有関係の問題なのです。

ExcelMaster には、フォームを普通の言葉で 伝えるだけで構いません — 「サイズの選択と色の選択、それぞれ独立」 — すると Frame を配置し、オプションボタン を正しくグループ化し、セクションの .Enabled をそれを制御するチェックボックスに配線してくれます。フォームと コードはあなたの手元に残り、グループはユーザーの期待どおりに振る舞います。

よくある質問

VBA の UserForm で Frame は何をしますか?

Frame は中のコントロールを所有するコンテナーです。目に見えるラベル付きの枠線を超えて、それらのコントロー ルをグループ化し、一緒に移動・有効化・非表示にします。そして、もっとも重要なのは、中の OptionButton の一 組を一つのグループとして排他的にすることです。Frame は自分自身の Controls コレクションも公開しているので、 そのセクションだけをループできます。

なぜオプションボタンがすべて一つのグループになってしまうのですか?

コンテナーを共有しているからです。OptionButton はその親の中で排他的で、フォームに直接置かれたボタンはすべ てフォームを親として共有します — だから選べるのは一つだけです。各組をそれぞれの Frame に入れる(または各組 に別々の GroupName を与える)ことで、独立したグループにしましょう。

グループ化における Frame と GroupName の違いは何ですか?

どちらもオプションボタンを排他的にします。Frame はグループ化 しつつ、単位として有効化・非表示・ループで きる目に見えるコンテナーを表示します。GroupName は目に見える箱なしで、共有する文字列によってグループ化しま す。グループ化が目に見える、または切り替え可能であるべきときは Frame を、コンテナーなしで排他性だけが必要な ときは GroupName を使いましょう。

Frame の中のコントロールだけをループするには?

Frame 自身のコレクションを使います:For Each ctl In fraSize.Controls。これにはその Frame を親とするコント ロールだけが入っているので、フォームの残りに触れずに、一つのグループの中で選ばれたオプションボタンを見つけら れます。.Value を読む前に、それぞれを TypeOf ctl Is MSForms.OptionButton で調べましょう。

Frame の中でコントロールの位置や親がおかしいのはなぜですか?

Frame に入ったコントロールの Parent はフォームではなく Frame で、.Left と .Top も Frame を基準に測ら れるからです。コントロールを Frame の中や外へ動かしたあとに予期しない場所に着地したり、フォームレベルの Controls ループがそれをトップレベルの項目として見つけられなかったりするなら、親チェーンの中の Frame が理 由です。

検証環境

検証環境: Excel 365 (Windows 11)、VBA 7.1 — 最終確認 2026-09-28。

関連ガイド: VBA Controls · VBA CheckBox · VBA UserForm · VBA ListBox · VBA ComboBox · VBA TextBox · VBA On Error