2方向のみのユーザーフォームオプションボタン

2020-02-11 excel vba userform

列と行のテーブルのように編成されたボタンを持つユーザーフォームがあります。列と行ごとにボタンを1つだけアクティブにしたい。 現時点では、すべてのボタンがオプションボタンであり、同じフレーム内の行のすべてのオプションボタンで機能します。 次に、列について、各ボタンにタイプのサブを書き込み始めました:

Private Sub Col1Row3_Click()

For i = 1 To 2
 Me.Controls("col1Row" & i) = False
Next i

For i = 4 To 14
 Me.Controls("col1Row" & i) = False
Next i

End Sub

それは機能しますが、もっとエレガントな方法があると私はかなり確信しています。何かご意見は ? よろしくお願いします!

Answers

簡単なサブ手順

あなたのアプローチに近いコードを簡素化する簡単な方法を実証しようとしました

  1. サブプロシージャを使用する
  2. ループですべてのオプションボタンをFalseに設定し、最終的にアクティブなボタンを再度Trueに設定します。
Sub Only(ByVal rowNum As Long, ByVal colName As String, Optional ByVal maxRow As Long = 14)
' Purpose: set all OptionButtons to False except the one for row rowNum
    Dim currRow     As Long
    For currRow = 1 To maxRow
        Me.Controls(colName & "Row" & currRow) = False
    Next
    Me.Controls(colName & "Row" & rowNum) = True
End Sub

複雑なループを回避する呼び出しの例

Private Sub col1Row3_Click()
    Only 3, "col1"
End Sub

さらにヒント

オプションボタンごとにプロシージャコールを繰り返す代わりに、クラスプログラミング(〜> WithEvents )から利益を得ることができます。より深い洞察のために、たとえば、クラスで事前定義された同じ名前タイプと同じイベントプロシージャを共有するコントロールをグループ化する場合は、 VBAコントロール配列に興味があるかもしれません。

それで、TMの助けのおかげで私の質問に答えるためだけに。

私は2つの可能性を見つけました:

コントロールがオプションボタンの場合、列と行ごとに1つだけ選択できるようにするには:

  • フレームの各行または列を持っている、この例の行を言うことができます
  • プロパティとしてのコントロールとメソッドとしてのcontrol_clickを持つクラスがあります。このメソッドは、列のすべてのコントロールをチェックします(controls.nameのタイプが「名前」&変数&numcolumnの場合、または列のプロパティ番号のおかげで、名前で見つかった列)。

すべてのタイプのコントロールの一般的なケースとそれをファック、私はクリックとして変更をとるチェックボックスでそれほど苦労することを期待していませんでした。

  • プロパティとしてのコントロールとメソッドとしてのcontrol_clickを持つクラスがあります。このメソッドは、クラスArr(コントロールの行、コントロールの列)のプロパティとしての配列のおかげで、または単に "名前"&行&列という名前のコントロールを持つ名前のおかげで、すべての行と列をチェックします

CheckBoxRxCyという名前のチェックボックスの例(つまり、CheckBoxR01C01)

モジュール内(私はすべてを宣言するために定義を使用します)

Public ClickCtrl  As Boolean 'the boolean which prevents the checkbox from going crazy

ClassForExclusivesクラス(tickboxが変更されたときにイベントを処理するクラス)

Public WithEvents ControlExcl As MSForms.CheckBox       'the control with events enabled


Private Sub ControlExcl_Click()

If ClickCtrl = False Then       'inhibits reaction to value change
GoTo line1

Else
For Each control2 In UserForm1.Controls

    If control2.Name <> ControlExcl.Name Then  'avoid setting the tickbox xhanged to false

        If Right(control2.Name, 2) = Right(ControlExcl.Name, 2) Or Mid(control2.Name, 10, 2) _
        = Mid(ControlExcl.Name, 10, 2) Then 'same row/col
        ClickCtrl = False
        control2.Value = False

        End If

    End If

ClickCtrl = True 'allows the clicks to trigger the code again

Next control2
End If

line1:

End Sub

ユーザーフォームで

Dim ArrControls() As New ClassForExclusives         'Set the array with the controls as ClassForExclusives

Private Sub UserForm_Initialize()
ClickCtrl = True

For Each Chkbox In Me.Controls
    If TypeOf Chkbox Is MSForms.CheckBox Then
        i = i + 1
        ReDim Preserve ArrControls(1 To i)
        Set ArrControls(i).ControlExcl = Chkbox

    End If
Next Chkbox
End Sub

Related