読者です 読者をやめる 読者になる 読者になる

C#ATIA

↑タイトル詐欺 主にCATIA V5 の VBA

Formの内容を、DrawTableに反映する

"CheckBoxにチェックの入った、TextBoxの文字のみを繋げて表示した"
と言うご質問を頂きました。
ひょっとしたら、僕の解釈が間違っているかもしれないので、
その際は指摘してください。

Formの内容をブログではちょっと扱いにくいのですが・・・。
(コードでFormを全て作成出来たのかな? それなら楽なのですが)

プロジェクトにUserForm(名前:UserForm1)を追加しコントロールを配置した
状態がこちら。
f:id:kandennti:20160310201822p:plain
基本的に、各コントロールは配置しただけの状態で、表示されている文字は
各コントロールの名前です。
(TextBoxのみ、配置しただけではコントロール名が表示された状態ではない
ため、修正しています)
ちょっと内容がCATIAっぽくなかったので、DrawTableに反映する
ボタンも追加しました。


以下のコードでは、TextBoxコントロール名が特に重要なので注意してください。
全てUserForm1のコードに書いてます。

'vba UserForm1Code
Option Explicit

Private CheckBoxs As Collection '全てのCheckBox

'**** Formイベント関連 ****
Private Sub UserForm_Initialize()
    Set CheckBoxs = New Collection
    Me.CheckBox1.Caption = "A": CheckBoxs.Add Me.CheckBox1
    Me.TextBox1.Text = "2"
    Me.CheckBox2.Caption = "B": CheckBoxs.Add Me.CheckBox2
    Me.TextBox2.Text = "3"
    Me.CheckBox3.Caption = "C": CheckBoxs.Add Me.CheckBox3
    Me.TextBox3.Text = "6"
    Me.CheckBox4.Caption = "D": CheckBoxs.Add Me.CheckBox4
    Me.TextBox4.Text = "1"
    
    Me.Label1.Caption = ""
    Me.Label1.BorderStyle = fmBorderStyleSingle
    Me.CommandButton1.Caption = "テーブルに反映"
End Sub

Private Sub UserForm_Terminate()
    Set CheckBoxs = Nothing
End Sub

Private Sub CheckBox1_Change()
    Me.Label1.Caption = ChangedCheckBox
End Sub

Private Sub CheckBox2_Change()
    Me.Label1.Caption = ChangedCheckBox
End Sub

Private Sub CheckBox3_Change()
    Me.Label1.Caption = ChangedCheckBox
End Sub

Private Sub CheckBox4_Change()
    Me.Label1.Caption = ChangedCheckBox
End Sub

Private Sub TextBox1_Change()
    Me.Label1.Caption = ChangedCheckBox
End Sub

Private Sub TextBox2_Change()
    Me.Label1.Caption = ChangedCheckBox
End Sub

Private Sub TextBox3_Change()
    Me.Label1.Caption = ChangedCheckBox
End Sub

Private Sub TextBox4_Change()
    Me.Label1.Caption = ChangedCheckBox
End Sub

Private Sub CommandButton1_Click()
    Me.Hide
    Call SetDrawTableCell
    Me.Show
End Sub

'**** Formサポート関数関連 ****
'CheckBox変更
'チェックの入ったCheckBoxに対応したTextBoxのTextだけを取得
Private Function ChangedCheckBox() As String
    Dim s$: s = ""
    Dim i%
    For i = 1 To CheckBoxs.Count
        If CheckBoxs.Item(i).Value Then
            s = s + Me.Controls("TextBox" + CStr(i)).Text
        End If
    Next
    ChangedCheckBox = s
End Function

'**** CATIA関連 **** 例外処理はほぼしていないです
'テーブルの選択
Private Sub SetDrawTableCell()
    Dim DrawDoc As DrawingDocument: Set DrawDoc = CATIA.ActiveDocument
    Dim ActSel: Set ActSel = DrawDoc.Selection
    
    ActSel.Clear
    Dim SelFilter: SelFilter = Array("DrawingTable")
    Dim SelMsg$: SelMsg = "反映するテーブルを選択して下さい : [Esc]=キャンセル"
    
    Select Case ActSel.SelectElement2(SelFilter, SelMsg, False)
        Case "Cancel", "Undo", "Redo"
            Exit Sub
    End Select
    '行(第2引数)と列(第3引数)は任意の数値にしてください
    Call SetCellString(ActSel.Item(1).Value, 1, 2, Me.Label1.Caption)
    ActSel.Clear
    Set DrawDoc = Nothing: Set ActSel = Nothing
End Sub

'テーブルのセルに反映
Private Sub SetCellString(ByRef DT As DrawingTable, ByVal Row%, ByVal Col%, ByVal Txt$)
    Txt = IIf(Len(Txt) < 1, "", Txt) 'チェック全て無しの場合の対応
    Call DT.SetCellString(Row, Col, Txt)
End Sub

UserForm_Initializeでは頂いたメールを元に初期設定しています。
任意のものに変更する必要があるかと思います。
又、後の処理の為にCheckBoxコントロール全てCheckBoxsコレクションに入れています。
(VBAではコントロールを配列で扱う事ができないです・・・恐らく)

ChangedCheckBox関数では、CheckBoxsコレクション内のCheckBoxのチェックを
確認し "True" になっているものだけ、対応したTextBoxの文字を
取得しています。

            s = s + Me.Controls("TextBox" + CStr(i)).Text

の部分がそうなのですが、該当するTextBoxをコントロール名で
探し出している為、TextBoxコントロール名が特に重要になります。
つまり

 CheckBoxsコレクションにAddした順番(インデックス) = "TextBox"+インデックス

の状態になっている必要があります。

こちらではストレスの無い程度の動きをしていたのですが、もし動作が
重いようであれば
TextBoxXXX_Changeイベントではなく、TextBoxXXX_AfterUpdateイベントに
変更すると軽くなるかと思います。
(現在は1文字変更するたびに、文字を取得する状態になっています)

と、書いたものの実はForm苦手なんです。
もっと良いコードをご存知の方がいましたら、教えて頂けると助かります。


念の為、TextBoxコレクション名の問題を避ける(任意の名前にしたい とか)
のであれば、TextBox用のコレクションを作成し対応するもの同士のインデックス
を一致させておくとか・・・。
DotNetのハッシュテーブルを呼び出してみるとか・・・
(確かVBAでも利用できたはず)


CheckBoxとTextBoxのChangeイベントが全部同じなのは、何とかならないの
かなぁ とは思うのですが、他の方法が無いような気がします。