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.
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
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. –
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