Solución:
Esto se puede lograr utilizando un módulo de clase. En el ejemplo que sigue, asumiré que ya tiene un formulario de usuario con algunos cuadros de texto.
En primer lugar, cree un módulo de clase en su proyecto VBA (llamemos clsTextBox
– ¡asegúrese de cambiar la propiedad ‘Nombre’ del módulo de clase!)
Private WithEvents MyTextBox As MSForms.TextBox
Public Property Set Control(tb As MSForms.TextBox)
Set MyTextBox = tb
End Property
Private Sub MyTextBox_Change()
AutoCalc() //call your AutoCalc sub / function whenever textbox changes
End Sub
Ahora, en el formulario de usuario, agregue el siguiente código:
Dim tbCollection As Collection
Private Sub UserForm_Initialize()
Dim ctrl As MSForms.Control
Dim obj As clsTextBox
Set tbCollection = New Collection
For Each ctrl In Me.Controls
If TypeOf ctrl Is MSForms.TextBox Then
Set obj = New clsTextBox
Set obj.Control = ctrl
tbCollection.Add obj
End If
Next ctrl
Set obj = Nothing
End Sub
El uso de clases, como sugiere la respuesta anterior, es una buena estrategia para manejar muchos controles de una manera concisa y elegante, sin embargo:
1) No veo problemas en la creación de 25 eventos con 1 línea, llamando a una rutina privada de formulario de usuario común, a menos que el número de controles sea dinámico. Es un BESO filosofía.
2) Generalmente, considero el Cambio Evento muy perturbador porque hace todo el recálculo de cada dígito ingresado. Es más sensato y moderado hacer esto usando el Salida evento o Antes de la actualización evento, porque hace el recálculo solo cuando se decide sobre un valor. Por ejemplo, el Google Instant Me molesta intentar devolver respuestas, consumiendo recursos, sin que el usuario haya definido la pregunta.
3) Hubo un problema de validación. Estoy de acuerdo en que puedes evitar claves incorrectas con Cambio evento, sin embargo, si necesita validar los datos, no puede saber si el usuario continuará escribiendo o si los datos están listos para ser validados.
4) Debes recordar que Cambio o Salida Los eventos no obligan al usuario a pasar campos de texto, por lo que el sistema debe ser revalidado y recalculado al intentar salir del formulario sin cancelar.
El siguiente código es simple pero efectivo para formularios estáticos.
Private Sub TextBox1_Exit(ByVal Cancel As MSForms.ReturnBoolean)
Call AutoCalc(Cancel)
End Sub
Private Sub TextBox2_Exit(ByVal Cancel As MSForms.ReturnBoolean)
Call AutoCalc(Cancel)
End Sub
.....
Private Sub TextBox25_Exit(ByVal Cancel As MSForms.ReturnBoolean)
Call AutoCalc(Cancel)
End Sub
Private Function Valid
.....
End Function
Private Sub AutoCalc(Canc As Variant)
If Not Valid() Then Canc=True
' Calculation
End Sub
Si es adicto a ahorrar tiempo, puede crear una rutina VBA genérica para generar código para eventos relacionados con controles en una forma que se ajuste a una máscara. Este código puede estar en una hoja de borrador (es más seguro generar código directamente, que tiene errores en algunas versiones de Excel) y que copiar y pegar en un módulo de formulario.
Sub GenerateEvent(Form As String, Mask As String, _
Evento As String, Code As String)
' Form - Form name in active workbook
' Mark - String piece inside control name
' Evento - Event name to form procedure name
' Code - Code line inside event
Dim F As Object
Dim I As Integer
Dim L As Long
Dim R As Range
Dim Off As Long
Set F = ThisWorkbook.VBProject.VBComponents(Form)
Set R = ActiveCell ' Destination code
Off = 0
For I = 0 To F.Designer.Controls.Count - 1
If F.Designer.Controls(I).Name Like "*" & Mask & "*" Then
R.Offset(Off, 0) = "Private Sub " & _
F.Designer.Controls(I).Name & "_" & Evento & "()"
R.Offset(Off + 1, 0) = " " & Code
R.Offset(Off + 2, 0) = "End Sub"
Off = Off + 4
End If
Next I
End Sub
Sub Test()
Call GenerateEvent("FServCons", "tDt", "Exit", _
"Call AtuaCalc(Cancel)")
End Sub
Eche un vistazo a esto para saber cómo crear una clase que responda a un cambio en cualquier cuadro de texto. El ejemplo es para botones, pero se puede modificar. Sin embargo, tenga en cuenta que los controles Textbox no tienen un evento Exit (ese evento es en realidad parte del formulario de usuario) por lo que realmente tendrá que usar el evento Change.