Access (VBA)

Access VBAに関するフォーラムです。
  • 解決済みのトピックにはコメントできません。
このトピックは解決済みです。
質問

 
(Windows 10 Home : Access 2016)
オプショングループ内にて、オプションボタンが未選択の場合の値の判定方法
投稿日時: 20/07/07 06:03:47
投稿者: かつん

オプショングループオブジェクト(frm1)の中に、オプションボタンが3つ(opt1、opt2、opt3)ある状態です。
opt1が選択された状態で、選択オプションの取得ボタン(btn7)をクリックすると、「オプション1が選択されています」と、MsgBoxが表示されるという簡易なプログラムです。そして、オプションボタンが何も選択されていない場合に、btn7をクリックした場合は、「オプションが選択されていません」と表示されます。
以下、コードになります。
 

select Case Me.frm1.Value
    Case opt1.OptionValue
        MsgBox "オプション1が選択されています"
    Case opt2.OptionValue
        MsgBox "オプション2が選択されています"
    Case opt3.OptionValue
        MsgBox "オプション3が選択されています"
    Case Else
        MsgBox "オプションが選択されていません"
        Debug.Print Me.frm1.Value
End Select

問題なく動きますし、意味も理解出来ています。最後のCase Elseに分岐した場合、イミディエイトウィンドウには「Null」と表示されます。つまりオプションボタンが何も選択されていない場合は、オプショングループオブジェクト(frm1)のValueプロパティはNullを返します。
それを踏まえて、以下のようにコードを少し書き変えました。
 
select Case Me.frm1.Value
    Case Null
        MsgBox "オプションが選択されていません"
    Case opt1.OptionValue
        MsgBox "オプション1が選択されています"
    Case opt2.OptionValue
        MsgBox "オプション2が選択されています"
    Case opt3.OptionValue
        MsgBox "オプション3が選択されています"
End Select

オプションボタンが何も選択されていない状態で、btn7をクリックしても無反応です。""や、vbNullStringなど色々試しましたがダメです。
 
長くなりましたが、オプショングループオブジェクト内のオプションボタンの未選択状態を判定するにはどうすればいいのでしょうか?手段としては、1つ目のコードを記述すれば良いというのは分かっています。ただ、2つめのコードのように書く場合どうすればいいのか分からないのは気持ちが悪いと思いまして、質問させていただきました。
 
何方かご教示よろしくお願いいたします。

回答
投稿日時: 20/07/07 09:13:08
投稿者: sk

引用:
オプションボタンが何も選択されていない場合は、
オプショングループオブジェクト(frm1)の
ValueプロパティはNullを返します。

引用:
select Case Me.frm1.Value
    Case Null

引用:
オプションボタンが何も選択されていない状態で、
btn7をクリックしても無反応です。

VBA の比較演算において、左辺または右辺の値が Null である場合、
その結果は True でもなく False でもなく Null です。
( Null 同士を比較しても True にはなりません)
 
つまり[frm1]の値が Null であり、かつその値をそのまま
評価している限り、Case Else 以外のブロックに
フローが分岐されることはありません。
 
引用:
2つめのコードのように書く場合どうすればいいのか

(例 1 : Null を別の値に変換して比較する)
--------------------------------------------------------------
Select Case Nz(Me.frm1.Value, "")
    Case ""
        MsgBox "オプションが選択されていません"
    Case opt1.OptionValue
        MsgBox "オプション1が選択されています"
    Case opt2.OptionValue
        MsgBox "オプション2が選択されています"
    Case opt3.OptionValue
        MsgBox "オプション3が選択されています"
End Select
--------------------------------------------------------------
 
(例 2 : 「比較演算の結果」と True を比較する)
--------------------------------------------------------------
Select Case True
    Case IsNull(Me.frm1.Value)
        MsgBox "オプションが選択されていません"
    Case Me.frm1.Value = opt1.OptionValue
        MsgBox "オプション1が選択されています"
    Case Me.frm1.Value = opt2.OptionValue
        MsgBox "オプション2が選択されています"
    Case Me.frm1.Value = opt3.OptionValue
        MsgBox "オプション3が選択されています"
End Select
--------------------------------------------------------------
 
(例 3 : Select Case とは別に Null 判定を行なう)
--------------------------------------------------------------
If IsNull(Me.frm1.Value) Then
    MsgBox "オプションが選択されていません"
    Exit Sub
End If
 
Select Case Me.frm1.Value
    Case opt1.OptionValue
        MsgBox "オプション1が選択されています"
    Case opt2.OptionValue
        MsgBox "オプション2が選択されています"
    Case opt3.OptionValue
        MsgBox "オプション3が選択されています"
    Case Else
        MsgBox "どのオプションとも異なる値(" & Me.frm1.Value & ")が設定されています"
        Debug.Print Me.frm1.Value
End Select
--------------------------------------------------------------

投稿日時: 20/07/08 05:45:31
投稿者: かつん

引用:
VBA の比較演算において、左辺または右辺の値が Null である場合、
その結果は True でもなく False でもなく Null です。
( Null 同士を比較しても True にはなりません)
  
つまり[frm1]の値が Null であり、かつその値をそのまま
評価している限り、Case Else 以外のブロックに
フローが分岐されることはありません。

 
skさん
ありがとうございます。上記の内容が全てですね。また、シンプルな内容かと思ったのですが、自分は理解が曖昧だったので改めて整理してみました。
 
まず、「Select Case」ステートメントって比較演算なの?と思いました。=や不等号ないけど?と疑問に思ったのですがよく考えれば・・・
 
select Case Me.frm1.Value
    Case opt1.OptionValue
上記Select Case文は、
If Me.frm1.Value = opt1.OptionValue
と、書き変えられるので、比較演算していますね。
 
また、
引用:
VBA の比較演算において、左辺または右辺の値が Null である場合、
その結果は True でもなく False でもなく Null です。

の部分は、TrueとかFalseの判断はBoolean型の変数などでない限り関係無いのでは?と思ったのですが、これもよく考えれば・・・
 
select Case Me.frm1.Value
    Case opt1.OptionValue
上記は、Me.frm1.Valueが、opt1.OptionValueなのかどうか?つまり、TrueかFalseかの2値で判断していますね。
 
自分の思考の整理の為に色々と書かせていただきました。
上記の考え方で問題ないでしょうか?

回答
投稿日時: 20/07/08 13:17:49
投稿者: sk

かつん さんの引用:
Select Case」ステートメントって比較演算なの?と思いました。
=や不等号ないけど?

Microsoft Docs より:
https://docs.microsoft.com/ja-jp/dotnet/visual-basic/language-reference/statements/select-case-statement
 
引用:
expression のみを指定する形式は、Is 形式の特殊なケースとして扱われます。
ここで、comparisonoperator は等号 (=) です。
この形式は testexpression = expression として評価されます

明示的に比較演算子を指定する場合は、
Is キーワードと合わせて記述します。
 
(参考例 1 )
---------------------------------------------------------
Dim i As Variant
 
i = 2
     
Select Case i
    Case Is <> 1
        Debug.Print "i の値は 1 ではない"
    'この場合は "Is = " を省略できる
    Case Is = 1
        Debug.Print "i の値は 1 である"
    Case Else
        Debug.Print "i の値は Null"
End Select
---------------------------------------------------------
 
かつん さんの引用:
上記は、Me.frm1.Valueが、opt1.OptionValueなのかどうか?
つまり、TrueかFalseかの2値で判断していますね。

Microsoft Docs より:
https://docs.microsoft.com/ja-jp/office/vba/language/reference/user-interface-help/comparison-operators
 
引用:
次の表に、比較演算子と、 _result_がTrue、 False、またはNullかどうかを決定する条件の一覧を示します。

(参考例 2 )
---------------------------------------------------------
Dim a As Variant
Dim b As Variant
Dim Result As Variant
 
a = 1
b = 1
Result = (a = b)
 
Debug.Print "a の値は " & a
Debug.Print "b の値は " & b
Debug.Print "Result の値は " & Nz(Result, "Null")
 
b = 2
Result = (a = b)
 
Debug.Print "a の値は " & a
Debug.Print "b の値は " & b
Debug.Print "Result の値は " & Nz(Result, "Null")
 
b = Null
Result = (a = b)
 
Debug.Print "a の値は " & a
Debug.Print "b の値は " & b
Debug.Print "Result の値は " & Nz(Result, "Null")
---------------------------------------------------------
 
かつん さんの引用:
上記の考え方で問題ないでしょうか?

概ね問題ないと思います。

投稿日時: 20/07/09 06:12:24
投稿者: かつん

skさん
 
参考URL、また例まで複数示していただきありがとうございます。
1時間ほど掛けてじっくり読ませていただきました(というより掛かってしまいました)。
ここまで深くSelect Case文や比較演算子について学習したことが無かったので、大変勉強になりました。また、この手の「技術ドキュメント」と言うのですかね?は小難しそうで、苦手意識がありましたが意外と読めるもんだなと、手ごたえのようなものも掴めました。
 
この度はご丁寧にありがとうございました。
恐らく、この先も質問する事があると思いますのでよろしくお願いいたします。