2017-12-31 236 views
2

私は22個のテキストボックスのグループを持っています。最初の20は1から10の間の数字で、textbox21は各グループの合計10です。私はtextbox1までtextbox20まで同じコードを持っていますが、どうすれば簡単にできますか?あなた以下20個のテキストボックスに対して1つのコードを20個のテキストボックスの代わりに合計22個のテキストボックスにする方法

は、これらのテキストボックスの1のために私が持っているコードを参照してください。

Private Sub TextBox1_Change() 
    korps(1) = 0 
    korps1 
    If TextBox1.Value = "" Then 
          TextBox1.SetFocus 
          Exit Sub 
    End If 
      If Not IsNumeric(TextBox1.Value) Then 
       MsgBox "Sorry, only numbers allowed" 
       TextBox1.Value = "" 
       Exit Sub 
      End If 
    If TextBox1.Value = 0 Then TextBox1.Value = 10 
    korps(1) = TextBox1.Value 
    korps1 
End Sub 
+0

私の最初の考えは次のようなものだと思います。たくさんの別々のテキストボックスが必要ですか?テキストボックスの違いは何ですか?テキストボックスを1つしか持たずに表示されたときに実行されるいくつかのコードに基づいて異なる動作をするか表示することができますか? – garbb

+2

ActiveX/MSFormsコントロールを想定すると、テキストボックスごとに1つのハンドラが必要になります。しかし、 'TextBox1_Change'のハンドラが' OnTextBoxChanged TextBox1'だけを含むように、独自の 'OnTextBoxChanged'プロシージャにロジックを抽出することができます。 –

+0

また、あなたは、組み込みの[InputBox関数()](https://msdn.microsoft.com/en-us/vba/excel-vba/articles/application-inputbox-method-excel)かもしれない見ているかもしれませんあなたがしようとしていることを単純化しますか? – garbb

答えて

3

フォームに名前txtBoxを持つクラスを作成することができ、私のコメントにリンクし、次のコード

Option Explicit 

Private WithEvents mTextBox As MSForms.Textbox 

Property Set Box(nBox As MSForms.Textbox) 
    Set mTextBox = nBox 
End Property 

Private Sub mTextBox_Change() 

    If mTextBox.Value = "" Then 
     mTextBox.SetFocus 
     Exit Sub 
    End If 
    If Not IsNumeric(mTextBox.Value) Then 
     MsgBox "Sorry, only numbers allowed" 
     mTextBox.Value = "" 
     Exit Sub 
    End If 
    If mTextBox.Value = 0 Then mTextBox.Value = 10 

End Sub 

に従っている場合は、次のコード

のようなコードが必要になりますここで
Option Explicit 

Dim colTxtBoxes As Collection 

Private Sub UserForm_Initialize() 

Dim m_txtBox As txtBox 
Dim ctl As MSForms.Control 

    Set colTxtBoxes = New Collection 

    For Each ctl In Me.Controls 

     If ctl.Name = "TextBox21" Or ctl.Name = "TextBox22" Then 
     Else 
      If TypeName(ctl) = "TextBox" Then 
       Set m_txtBox = New txtBox 
       Set m_txtBox.Box = ctl 
       colTxtBoxes.Add m_txtBox 
      End If 
     End If 

    Next ctl 

End Sub 
+0

ありがとう、完璧に動作します! – Chielmos

0

は一度だけのコードを必要とするソリューションです。以下は必要な手順です。それらは、すべてのテキストボックスがあるUserformのコードシートになければなりません。ご覧のとおり

Option Explicit 

    Dim Korps() As Long 

Private Sub UserForm_Initialize() 
    ' 01 Jan 2018 
    ' presuming that all Tbxs are 0 upon initialisation. 
    ' if they are not, transfer their initial values to Korps here. 

    ReDim Korps(1 To 10, 1 To 2) 
    SetTotals 
End Sub 

Private Function KeyPress(Tbx As MSForms.TextBox, _ 
          ByVal Key As Integer) As Integer 
    ' 01 Jan 2018 
    ' Message is shown after each 3rd wrong entry, 
    ' regardless of the Tbx in which it occurred. 

    Static Count As Integer 

    If Not IsNumeric(Chr(Key)) Then 
     Key = 0 
     Count = Count + 1 
     If Count = 3 Then 
      MsgBox "Only numbers may be entered", _ 
        vbInformation, "Entry restrictions" 
      Count = 0 
     End If 
    End If 
    KeyPress = Key 
End Function 

Private Sub TbxUpdate(Tbx As MSForms.TextBox) 
    ' 01 Jan 2018 

    Dim Idx As Integer      ' Tbx number 
    Dim Grp As Integer      ' 1 = 1 to 10, 2 = 11 to 20 

    With Tbx 
     Idx = Mid(.Name, Len("TextBox") + 1) 
     Grp = Int((Idx - 1)/10) + 1 
     If Trim(.Text) = "" Then 
      ' reject blank: restore previous value 
      .Value = Korps(Idx, Grp) 
      .SetFocus 
     Else 
      If .Value = 0 Then .Value = 10 
      Korps(Idx, Grp) = .Value 
      SetTotals Grp 
     End If 
    End With 
End Sub 

Private Sub SetTotals(Optional ByVal Grp As Integer) 
    ' 01 Jan 2018 
    ' if Grp isn't supplied, both groups are summed up 

    Dim Ttl As Double 
    Dim LoopStart As Integer, LoopEnd As Integer 
    Dim i As Long 

    If Grp Then 
     LoopStart = Grp 
     LoopEnd = Grp 
    Else 
     LoopStart = 1 
     LoopEnd = 2 
    End If 

    For Grp = LoopStart To LoopEnd 
     Ttl = 0 
     For i = 1 To 10 
      Ttl = Ttl + Korps(i, Grp) 
     Next i 
     Me.Controls("TextBox2" & Grp).Value = Ttl 
    Next Grp 
End Sub 

は、私はあなたの変数korpsと手順korps1は何をすべきかを推測しました。次のイベントプロシージャが必要になりますあなたの20個のテキストボックスのそれぞれについて

。それらは宣言のTextBox番号を除いてすべて同じです。ここでは、代わりにクラスを作成するStoraxの提案の優位性があります。あなたがクラスを作成することに慣れているなら、私はそれを推奨するべきです。

Private Sub TextBox1_BeforeUpdate(ByVal Cancel As MSForms.ReturnBoolean) 
    ' 01 Jan 2018 
    TbxUpdate ActiveControl 
End Sub 

Private Sub TextBox1_KeyPress(ByVal KeyAscii As MSForms.ReturnInteger) 
    ' 01 Jan 2018 
    KeyAscii = KeyPress(ActiveControl, KeyAscii) 
End Sub 

あなたが考えていたものとは異なるイベントを使用することをお勧めします。あなたがクラスを作ることを選んだとしても、再考すべきだと思います。 Changeイベントは、入力されたすべての文字で発生します。これは、数字以外の項目をキャッチする目的で便利です。ただし、KeyPressイベントは、テキストボックスに表示される文字を停止できるため、イベントにさらに適しています。ランニング合計を維持するように

複数桁の数字が入力されたとき、それは無意味な合計を作成するため、Changeイベントは冒険です。代わりにユーザーがフォーカス(およびカーソル)を別のコントロールに移動したときに発生するUpdateイベントを推奨します。

+0

Variatusさん、ありがとう、私に非常に良い選択肢を与えました。 – Chielmos

関連する問題