2017-12-31 149 views
2

Ich habe eine Gruppe von 22 Textfeldern. Die ersten 20 sind Zahlen zwischen 1 und 10 und textbox21 ein Textfeld22 ist die Summe jeder Gruppe von 10. Ich habe für textbox1 bis textbox20 den gleichen Code, aber wie kann ich das einfacher machen?Wie man einen Code für 20 Textfelder aus insgesamt 22 Textfeldern statt 20 Mal gleich macht

Unten sehen Sie den Code, den ich für eine dieser Textfelder habe.

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

Ich denke, mein erster Gedanke wäre: Müssen Sie so viele separate Textfelder haben? Was sind die Unterschiede zwischen den Textfeldern? Könnten Sie nur ein Textfeld haben und es dann anders verhalten oder anzeigen, basierend auf Code, der beim Erscheinen ausgeführt wird? – garbb

+2

Unter der Voraussetzung, dass ActiveX/MSForms-Steuerelemente verwendet werden, benötigen Sie einen Handler pro Textfeld und keine Umgehung. So funktionieren Ereignisse. Aber Sie können die Logik in eine eigene 'OnTextBoxChanged'-Prozedur extrahieren, wie beispielsweise die Prozedur für' TextBox1_Change' nur 'OnTextBoxChanged TextBox1' enthält. –

+0

Sie könnten auch die integrierte [inputbox()] (https://msdn.microsoft.com/en-us/vba/excel-vba/articles/application-inputbox-method-excel) ansehen, die möglicherweise vereinfachen, was Sie versuchen zu tun? – garbb

Antwort

3

Wenn Sie den Link in meinem Kommentar folgen Sie eine Klasse mit dem Namen müssten txtBox und den folgenden Code

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 

In Form erstellen können Sie einen Code ähnlich dem folgenden Code

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

Vielen Dank, es funktioniert perfekt! – Chielmos

0

Hier ist eine Lösung, die den Code nur einmal benötigt. Im Folgenden finden Sie die Verfahren, die Sie benötigen. Sie sollten im Codeblatt der Benutzerform sein, auf der Sie alle Textfelder haben.

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 

Wie Sie sehen, habe ich eine Vermutung an, was Ihre Variable korps und die Prozedur korps1 tun.

Für jede Ihrer 20 Textfelder benötigen Sie die folgenden Ereignisprozeduren. Sie sind alle gleich, mit Ausnahme der TextBox-Nummer in ihren Deklarationen. Hierin liegt die Überlegenheit von Storax 'Vorschlag, stattdessen eine Klasse zu schaffen. Wenn Sie mit der Erstellung einer Klasse zufrieden sind, die ich empfehlen sollte.

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 

Beachten Sie, dass ich vorschlage, Ereignisse zu verwenden, die sich von denen unterscheiden, an die Sie gedacht haben. Ich denke, Sie sollten es sich noch einmal überdenken, selbst wenn Sie sich dafür entscheiden, eine Klasse zu erstellen. Das Ereignis Change wird bei jedem eingegebenen Zeichen ausgelöst. Dies ist nützlich, um nicht-numerische Einträge abzufangen, außer dass das Ereignis KeyPress dafür noch besser geeignet ist, da es das Zeichen in der Textbox stoppen kann.

Das Ereignis Change ist für die Aufrechterhaltung einer laufenden Summe abenteuerlich, weil es sinnlose Summen erzeugt, wenn mehrstellige Zahlen eingegeben werden. Ich empfehle stattdessen das Ereignis Update, das auftritt, wenn der Benutzer seinen Fokus (und den Cursor) auf ein anderes Steuerelement verschiebt.

+0

Danke Variatus, du hast mir eine sehr gute Alternative gegeben. – Chielmos

Verwandte Themen