martes, 14 de enero de 2020

Crear registros en hoja BASE con Userform

Son muchas las ocasiones en que necesitamos crear registros e ir acumulándolos en una hoja tipo BASE, de modo lineal. Es decir 1 registro por fila con cantidad de columnas según los campos utilizados.

En esta entrada vamos a ver cómo se realiza un formulario de REGISTRO. En entradas posteriores hablaremos de las opciones de Modificar y Eliminar registros de esa base.

El siguiente modelo, que servirá para cualquier tipo de actividad (Clientes, Proveedores, Alumnos, Pacientes, etc) tendrá campos del tipo:
- Label: que permiten mostrar información que luego será guardada en una columna. En ese caso se trata de un código o número de Identificación del registro.
- Textbox: son los campos para introducir valores o textos.
- ComboBox: un desplegable para seleccionar algún elemento de una lista.
- CommandButton: los botones de acción: Aceptar, Cancelar y Salir.


A partir de este modelo podremos agregar más controles y más columnas en la hoja que actualmente presenta este orden:

Por ejemplo, podríamos agregar un control Label para la fecha del día y más controles TextBox y ComboBox para ingreso o selección de datos.

Al pie encontrarán el enlace para descargar el formulario con su programación completa.

¿Qué vamos a tener en cuenta al momento de programar un formulario de REGISTRO? 

1- Los LABEL los utilizamos para mostrar información que luego puede ser guardada en el registro o no. Será el campo de la numeración automática de registro. Es decir un control que no será modificado por el usuario.
          Label7.Caption = Application.WorksheetFunction.Max(hop.Range("A:A")) + 1

2- Los TEXTBOX pueden ser controlados al momento del ingreso. Por ejemplo un control de valores numéricos:
         Private Sub TextBox7_KeyPress(ByVal KeyAscii As MSForms.ReturnInteger)
          If KeyAscii < 48 Or KeyAscii > 57 Then
             KeyAscii = 0
             MsgBox "Error en el dato. Solo se aceptan valores numéricos."
          End If
         End Sub

También pueden ser convertidos como el campo nombre pasándolo a mayúsculas a medida que se registra en él:
         Private Sub TextBox4_Change()
         TextBox4 = UCase(TextBox4)
         End Sub

3- Al inicio del módulo Userform se declara una variable para guardar el nombre de la hoja BASE.
         Dim hob

Y desde el evento INITIALIZE del formulario se guarda en esa variable el nombre de la hoja de base. Esto servirá para mover la información a la hoja sin necesidad de activarla o seleccionarla previamente.
También en este evento de inicio se guarda en el Label el número del registro a crear.
         Private Sub UserForm_Initialize()
         Set hop = Sheets("PROVEEDORES")
         'otras instrucciones
         Label7.Caption = Application.WorksheetFunction.Max(hop.Range("A:A")) + 1
         End Sub

4- Al ACEPTAR se debe verificar que haya un dato clave, que en este caso es el nombre. Incluir en este control previo todos los campos que sean de caracter obligatorio. Y siempre es recomendable enviar un mensaje de confirmación.
         Private Sub Aceptar_Click()
         If TextBox4 = "" Then
              MsgBox "Falta el nombre del Proveedor.", , "Faltan Datos"
              TextBox4.SetFocus
              Exit Sub
         End If
         sino = MsgBox("¿Deseas guardar estos datos?", vbQuestion + vbYesNo, "Confirmar")
         If sino <> vbYes Then Exit Sub

5- Al realizar el pase a la hoja se tendrá en cuenta el tipo de dato. Los controles utilizados son del tipo 'texto' por lo tanto tendremos que convertirlos con las siguientes funciones:
   - VAL para guardar valores numéricos enteros.
   - CDBL  para guardar valores numéricos con decimales. Evaluar si el control se encuentra vacío.
'se pasa el registro. se busca la fila libre
fily = hop.Range("A" & Rows.Count).End(xlUp).Row + 1
hop.Range("A" & fily) = Label7.Caption
hop.Range("B" & fily) = TextBox4
hop.Range("C" & fily) = TextBox6
hop.Range("D" & fily) = ComboBox1.Text
hop.Range("E" & fily) = Val(TextBox7)
If TextBox11 <> "" Then hop.Range("F" & fily) = CDbl(TextBox11)
hop.Range("G" & fily) = TextBox9
hop.Range("H" & fily) = TextBox10

Como la columna de SALDO ya presenta un formato 'Moneda' con decimales y de color rojo para los negativos, que fue asignado desde la misma hoja para la columna completa no será necesario asignarle formato a la hora de guardar los campos.

6- Al finalizar el pase se limpiará el formulario para permitir un nuevo registro. Para esto se llamará a la misma macro que la del botón CANCELAR:
Call Cancelar_Click
End Sub

7- La macro para CANCELAR limpia los controles y actualiza nuevamente el número para el ID correlativo.
         Private Sub Cancelar_Click()
         'se limpian los textbox
         For Each ct In Me.Controls
             If TypeName(ct) = "TextBox" Then ct.Value = ""
         Next ct
         'se limpia el combobox
         ComboBox1.ListIndex = -1
         'se incrementa el ID del prov.
         Label7.Caption = Application.WorksheetFunction.Max(hop.Range("A:A")) + 1
         TextBox4.SetFocus
         End Sub

8- El botón SALIR cierra el Userform. Recordar que si se desprotegió (y quizás se mostró hoja oculta) habrá que volverla a proteger y ocultar. Esto se instruye en el evento de cierre:
         Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
         hop.Protect
         End Sub

Descargar el ejemplo con su código desde aquí

Ver VIDEO N° 27.

4 comentarios:

  1. Respuestas
    1. Gracias por comentar. En la siguiente entrada encontrarás las macros para 'Modificar y Eliminar' los registros creados. Sdos!

      Borrar
  2. Estimada Matilde: Vi el el material que me recomendó. Soy la persona que preguntó sobre UserForm en TodoExpertos y Ud. amablemente me respondió. Quiero comentarle que estoy tratando de usar la herramienta excel (en la cual soy apenas un usuario de medio/bajo nivel) para desarrollar estructuras (y conocimiento) como para manejar tablas de distintas estructuras, datos y características pero todas ellas vinculadas en forma relacional. Seguramente estará pensando por qué no uso herramientas más propias de manejo de información relacional y la respuesta es básicamente costo, disponibilidad, portabilidad y sobre todo posibilidad de usuarios "comunes" que normalmente pueden acceder a herramientas office pero no a herramientas más pesadas y caras. Bueno, en este escenario mi intención es poder manejar tablas en la forma más elástica posible (distintos libros, distintas hojas, distintos estados de protección y filtro, distintos tipos de datos, distintos tamaños y agrupamientos, etc. Es decir todo lo que alguien podría llegar a necesitar y se pueda registrar en Excel. Pero por supuesto quiero llegar a tener la solidez, consistencia y normalización que me permitiría una herramienta mayor y además la posibilidad de escalamiento, es decir empezar con un pequeño módulo de ABM de "algo" para terminar en un desarrollocompleto que incluya mantenimiento, historia, consultas, seguridad.... etc. y posibilitar el uso por parte de usuarios-usuarios y por parte de usuarios-administradores y usuarios de sistemas. En otras palabras, aprovechar las características y familiaridad de excel pero apuntando a algo que vaya desde un core intocable por usuarios hasta un front-end que sea tan amigable como posible.
    Es un objetivo ambicioso que tengo y me interesa por ahora aprender tanto como sea posible para avanzar en ello pero a medida que avanzo me encuentro con dos cosas: 1)Mi falta de conocimiento avanzado 2)Falta de información y formación específica orientada a ello. Por todo lo expresado, me gustaría pedirle su opinión personal sobre si la herramienta Excel realmente posibilitaría este objetivo con una inversión de esfuerzo y tiempo razonable y con una suficiente solidez esperable en el resultado. Su opinión me parece muy importante porque viendo su material tengo la sensación de que Ud. es una persona que puede dar una opinión válida y respetable. Le comento que en este "empezar" a veces me encuentro con cosas que parecen ser simples pero me traen problemas por falta de herramientas específicas o "preparadas" pertenecientes a la herramienta. Por ejemplo el uso de funciones de la aplicación o de la hoja (Application. o Worksheet functions) que a veces parecen ser soluciones a pequeñas necesidades, también a veces aparejan dificultades como necesitar ser cuidadosos con la hoja activa o referenciada. Un caso simple es vLookUp, que funciona o no funciona dependiendo de lo antedicho, por lo cual la "solidez" y seguridad de operación termina siendo más confiable usando utilería rudimentaria, vieja y sólida como un for/next, que siempre funciona pero requiere más líneas de código, más proceso, más control y no sé si en tablas muy grandes podría ser notable también el tiempo de respuesta). Es decir... como puede ver estoy "en pañales" pero tengo la intención de seguir avanzando y en este momento me animo a rogarle por su opinión sobre la relación entre esta herramienta y el objetivo planteado. Muchas grancias por anticipado. Atentamente.

    ResponderBorrar
  3. Hola Heinrich. Me gustaría que me contactes al correo (gmail) para intercambiar algunas ideas con respecto a tu comentario. Lo encontrarás en mi perfil (actualizado;). También aparece en la sección Contacto de mi web. Saludos!

    ResponderBorrar