web-dev-qa-db-ja.com

ユーザーフォームから動的に追加されたコントロールを削除する

チェックボックスが動的に追加されたExcelユーザーフォームがあります。

次のようなコードでチェックボックスを追加します。

Set chkBox = Me.Controls.Add("Forms.Checkbox.1", "Checkbox" & i)

これらのチェックボックスをすべて削除したいと思います。

Dim j As Integer
'Remove all dynamically updated checkboxes
For Each cont In Me.Controls
    For j = 1 To NumControls
        If cont.Name = "Checkbox" & j Then
            Me.Controls.Remove ("Checkbox" & j)
        End If
    Next j
Next cont

次のエラーメッセージが表示されます。
Error MEssage

10
ale10ander

より良いアプローチは、作成したコントロール(たとえば、コレクション内)を追跡し、それを使用して削除することです。

このようにして、コードは名前形式にバインドされず、他のコントロールタイプにも適用できます。

Private cbxs As Collection

Private Sub UserForm_Initialize()
    Set cbxs = New Collection
End Sub

' Remove all dynamicly added Controls
Private Sub btnRemove_Click()
    Dim i As Long
    Do While cbxs.Count > 0
        Me.Controls.Remove cbxs.Item(1).Name
        cbxs.Remove 1
    Loop
End Sub


' Add some Controls, example for testing purposes
Private Sub btnAdd_Click()
    Dim i As Long
    Dim chkBox As Control
    For i = 1 To 10
        Set chkBox = Me.Controls.Add("Forms.CheckBox.1", "SomeRandomName" & i)
        chkBox.Top = 40 + i * 20
        chkBox.Left = 20
        cbxs.Add chkBox, chkBox.Name  ' <-- populate tracking collection
    Next

    ' Demo that it works for other control types
    For i = 1 To 10
        Set chkBox = Me.Controls.Add("Forms.ListBox.1", "SomeOtherRandomName" & i)
        chkBox.Top = 40 + i * 20
        chkBox.Left = 60
        chkBox.Add chkBox, chkBox.Name
    Next

End Sub
12
chris neilsen

「チェックボックス」で始まる他のコントロール名がないと仮定すると、

For Each cont In Me.Controls
    If InStr(cont.Name, "Checkbox") = 1 Then
        Me.Controls.Remove cont.Name
    End If
Next cont
3

コントロールの名前、タイプ、および数がすでにわかっている場合、なぜ二重ループなのでしょうか。

削除できるのは、実行時に作成されたコントロールのみであることに注意してください。

'the following removes all controls created at runtime
Dim i As Long
On Error Resume Next
With Me.Controls
    For i = .Count - 1 to 0 step -1
        .Remove i
    Next i
End With
Err.Clear: On Error GoTo 0

そしてあなたの場合: 'すべての命名が正しい場合

Dim j&
For j = 1 To NumControls
    Me.Controls.Remove "Checkbox" & j
Next j
2

コントロールのチェックを追加すると、これが修正されたようです。理由は完全にはわかりませんが、動作します。

   Dim j As Integer
'Remove all dynamically updated checkboxes
For Each cont In Me.Controls
    If TypeName(cont) = "CheckBox" Then
        For j = 1 To NumControls
            If cont.Name = "Checkbox" & j Then
                Me.Controls.Remove cont.Name
                Exit For
            End If
        Next j
    End If
Next cont
1
ale10ander

保持するコントロールと削除するコントロールを選択するもう1つの方法は、.Tag属性を使用することです。これにより、たとえば.Tagをビットフィールドとして使用することにより、追加されたコントロールを細かく制御できます。

作成時:

With Me.Controls.add("Forms.Label.1", Visible:=True)
{code}
    .Tag = 1
{more code}

次に、片付けの時間が来たら、

For Each C In Me.Controls
    If C.Tag = 1 Then Me.Controls.Remove C.Name
Next
0
bodgesoc

コマンドボタンを使用して元のコードを書き直し、「NumControls」ではなく「Me.Controls.Count」を追加し、「Cont」をコントロールとして定義しました。それは私のために働いているようです。これがあなたのために働くかどうか私に知らせてください:

->

On Error Resume Next
Dim Cont As Control
Dim C As Integer
'Remove all dynamically updated checkboxes
For Each Cont In Me.Controls
    For C = 1 To Me.Controls.Count
    If Cont.Name = "CommandButton" & C Then
        Me.Controls.Remove ("CommandButton" & C)
    End If
    Next C
Next Cont
0
MrPantsMan