2017-12-31 166 views
2

22 개의 텍스트 상자 그룹이 있습니다. 첫 번째 20은 1에서 10 사이의 숫자이고 textbox21은 각 그룹의 합계 인 10입니다. textbox1까지 textbox20까지 동일한 코드가 있지만 어떻게 더 쉽게 만들 수 있습니까?20 개의 텍스트 상자에 대해 하나의 코드를 만드는 방법 20 개의 동일한 텍스트 상자 대신 22 개의 텍스트 상자를 사용하는 방법

아래 텍스트 상자 중 하나에 대한 코드가 있습니다.

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

내 첫 번째 생각은 다음과 같을 것입니다. 많은 개별 텍스트 상자가 필요합니까? 텍스트 상자의 차이점은 무엇입니까? 하나의 텍스트 상자가 있고 그 텍스트 상자가 나타날 때 실행되는 일부 코드에 따라 다르게 표시되거나 표시 될 수 있습니까? – garbb

+2

ActiveX/MSForms 컨트롤을 사용하는 경우 텍스트 상자 당 하나의 핸들러가 필요하며 주위에는 이벤트가 작동하는 방식이 필요하지 않습니다. 그러나 '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