🗂️ CRUD en VBA con UserForm
Desde una hoja vacía hasta un formulario que Crea, Busca, Actualiza y Elimina filas de una tabla en Excel — con código 100% copiable.
🟦 ¿Quieres el mismo formulario en TypeScript/JavaScript? Mira su gemelo: CRUD en TypeScript
📖 Teoría
¿Qué es una "tabla" aquí?
Un rango de celdas donde la fila 1 tiene los encabezados (ID, Nombre, Descripcion, IdCategoria, Entradas, Salidas, Cantidad) y cada fila siguiente es un registro de inventario. Trabajamos directo con celdas, sin el objeto "Tabla" de Excel, para entender exactamente qué hace cada línea de código.
¿Qué es un UserForm?
Una ventana propia diseñada dentro del editor de VBA, con cajas de texto y botones. En vez de escribir directo en las celdas, el usuario llena el formulario y presiona un botón.
¿Qué es CRUD?
Las 4 operaciones que cualquier sistema de datos necesita: Crear, Leer, Actualizar, Eliminar (en inglés: Create, Read, Update, Delete).
El resultado final
Un UserForm con 7 campos y 5 botones. Cada botón ejecuta una operación CRUD (más un botón para limpiar los campos) sobre una hoja de inventario llamada Productos.
Crea una hoja nueva y ponle exactamente el nombre Productos (clic derecho sobre la pestaña → Cambiar nombre). En la fila 1 escribe estos 7 encabezados:
| Columna | Encabezado | Contenido esperado |
|---|---|---|
| A1 | ID | Número consecutivo, lo asigna el código automáticamente |
| B1 | Nombre | Texto |
| C1 | Descripcion | Texto |
| D1 | IdCategoria | Número (referencia al ID de una categoría) |
| E1 | Entradas | Número (unidades que han ingresado) |
| F1 | Salidas | Número (unidades que han salido) |
| G1 | Cantidad | Número (existencia actual) |
Esta es la fila real que necesitas en A1 — sin columnas de más, lista para pegar o descargar:
| ID | Nombre | Descripcion | IdCategoria | Entradas | Salidas | Cantidad |
|---|
El archivo descargado se puede llamar y guardar como quieras (ej. "hoja_Productos.xlsx") — lo que sí trae listo, y no debes cambiar, es la pestaña interna llamada Productos, que es la que lee el código VBA.
⚠️ Atención: el nombre de la hoja debe ser Productos exacto. Todo el código usa ThisWorkbook.Sheets("Productos") — si la hoja se llama distinto, VBA lanza el error "Subscript out of range".
Abre el editor de VBA con Alt + F11, luego Insertar → UserForm.
- Con el formulario seleccionado, abre Propiedades (
F4) y cambia su(Name)afrmProductos. - Arrastra 7 TextBox y 5 CommandButton al formulario.
- Renombra cada control (propiedad
(Name)) exactamente como en la tabla — el código de los siguientes pasos depende de estos nombres.
| Tipo | Name | Caption / uso |
|---|---|---|
| TextBox | txtID | ID del registro (buscar, actualizar, eliminar) |
| TextBox | txtNombre | Nombre del producto |
| TextBox | txtDescripcion | Descripción del producto |
| TextBox | txtIdCategoria | ID de la categoría a la que pertenece |
| TextBox | txtEntradas | Unidades que han entrado (compras/ingresos) |
| TextBox | txtSalidas | Unidades que han salido (ventas/consumos) |
| TextBox | txtCantidad | Existencia actual en inventario |
| CommandButton | btnCrear | Caption: "Crear" |
| CommandButton | btnBuscar | Caption: "Buscar" |
| CommandButton | btnActualizar | Caption: "Actualizar" |
| CommandButton | btnEliminar | Caption: "Eliminar" |
| CommandButton | btnLimpiar | Caption: "Limpiar" |
💡 Nota: estos nombres se escriben a mano en la ventana de Propiedades (F4) de cada control dentro del editor de VBA — esta tabla es solo de consulta, no se pega en una hoja de cálculo.
Así se ve el formulario terminado (esquema, no una captura real):
💡 Truco: renombra cada control apenas lo arrastras, antes de agregar el siguiente. Si dejas los nombres por defecto y programas primero, tendrás que volver a cada línea de código a corregirlos.
Haz doble clic sobre el formulario (o cualquiera de sus controles) para abrir su módulo de código, y pega esto arriba de todo.
Buscar la fila de un ID — recorre la columna A y devuelve el número de fila donde encuentra ese ID, o 0 si no existe:
Limpiar los campos — vacía los 7 TextBox y devuelve el cursor al primero. La llamarás desde Crear, Eliminar y desde el propio botón Limpiar:
💡 ¿Por qué "Private Function… As Long"? Long es un tipo numérico entero, suficiente para un ID o un número de fila. Private significa que solo el código de este mismo formulario puede llamarla.
Haz doble clic sobre btnCrear en el diseñador. VBA abre su evento Click vacío — pega el código dentro.
Set ws = ThisWorkbook.Sheets("Productos")— apuntawsa la hoja Productos.ws.Cells(ws.Rows.Count, "A").End(xlUp).Row + 1— el truco de "Ctrl + flecha abajo" pero en código: da la primera fila vacía.Val(Me.txtIdCategoria.Value)— convierte el texto a número; si está vacío, devuelve 0 en vez de dar error. Lo mismo aplica a Entradas, Salidas y Cantidad.
❌ Error común: guardar IdCategoria/Entradas/Salidas/Cantidad sin Val(...) puede dejar texto vacío en una celda que debería ser numérica, y tus sumas fallarán en silencio.
"Leer" aquí significa: dado un ID, traer ese registro y llenar el formulario con sus datos.
💡 Por qué es "Leer": consulta datos existentes sin modificarlos. Actualizar y Eliminar dependen de haber hecho primero un Buscar.
Flujo esperado: primero Buscar (ubica la fila y carga los datos), el usuario edita, y presiona Actualizar.
⚠️ Diferencia con Crear: Crear siempre agrega una fila nueva; Actualizar siempre escribe sobre una fila que ya existe. Nunca toca la columna ID.
La operación más delicada: no se puede deshacer con un botón del formulario, así que pedimos confirmación antes de borrar.
❌ Regla de oro: nunca elimines directo al hacer clic. Un MsgBox con vbYesNo es la diferencia entre un error que se corrige en dos segundos y una fila perdida para siempre.
Ya tienes las 4 operaciones. Faltan dos detalles: el botón que vacía el formulario a mano, y una forma de abrirlo sin pasar por el editor de VBA.
Por último, crea un Módulo normal (clic derecho en el proyecto → Insertar → Módulo) con esta macro, y asígnala a un botón dibujado en tu hoja de Excel:
💡 Cómo asignarla: en la hoja de Excel, Insertar → Formas, dibuja el botón, clic derecho → "Asignar macro" → elige MostrarFormulario.
| Síntoma | Causa probable |
|---|---|
| "Subscript out of range" | La hoja no se llama exactamente "Productos" |
| "Object doesn't support this property or method" | Un control tiene un nombre distinto al que usa el código (txtNombre mal escrito, etc.) |
| Se crean filas duplicadas | Se llamó a Crear en vez de Actualizar sobre un registro existente |
| Las macros no aparecen al reabrir el archivo | Se guardó como .xlsx en vez de .xlsm (Libro habilitado para macros) |
| IdCategoria/Entradas/Salidas/Cantidad quedan como texto | Se guardó el TextBox sin envolver con Val() |
🧪 Simulador: cómo viaja el dato
Resume en cámara lenta lo que hace btnCrear_Click: los valores del formulario se copian, celda por celda, a una fila nueva de la hoja Productos.
UserForm (frmProductos)
Hoja "Productos"
| ID | Nombre | Descripcion | IdCategoria | Entradas | Salidas | Cantidad |
|---|---|---|---|---|---|---|
| 1 | Lámpara de pie | Lámpara de lectura, base de madera | 5 | 12 | 5 | 7 |
💡 Lo mismo pasa al revés en "Leer": el dato viaja de la tabla hacia el formulario. Actualizar y Eliminar primero leen la fila (para ubicarla) y luego escriben o borran sobre ella.
📚 Diccionario
CRUD: Crear, Leer, Actualizar, Eliminar — las 4 operaciones básicas de cualquier sistema de datos.
UserForm: Ventana propia diseñada en VBA con controles (cajas de texto, botones) para interactuar con el usuario.
TextBox: Control de UserForm donde el usuario escribe texto o números.
CommandButton: Botón de UserForm que ejecuta código al presionarlo (evento Click).
Módulo: Contenedor de código VBA sin interfaz visual, distinto de un UserForm.
ThisWorkbook: Objeto que representa el libro de Excel actual donde vive el código.
Worksheet: Objeto que representa una hoja de cálculo dentro del libro.
Range / Cells: Formas de referirse a celdas. Range usa texto ("A1"); Cells usa números (fila, columna).
Dim: Palabra clave para declarar una variable y su tipo de dato.
Long: Tipo de dato numérico entero, ideal para IDs y números de fila.
Val(): Convierte texto a número; devuelve 0 si el texto está vacío o no es numérico.
CLng(): Convierte un valor a número entero largo (Long).
Trim(): Quita los espacios en blanco al inicio y al final de un texto.
MsgBox: Muestra un cuadro de diálogo con un mensaje, íconos y botones configurables.
vbYesNo: Constante que agrega los botones "Sí" y "No" a un MsgBox.
VbMsgBoxResult: Tipo de dato que guarda cuál botón presionó el usuario en un MsgBox.
Me: Dentro del código de un UserForm, hace referencia al propio formulario en ejecución.
SetFocus: Método que coloca el cursor dentro de un control determinado.
End(xlUp): Truco de código equivalente a Ctrl+Flecha arriba: encuentra la última celda con datos.
Private / Public: Alcance de un procedimiento: solo su módulo (Private) o todo el proyecto (Public).
.xlsm: Formato "Libro de Excel habilitado para macros", necesario para conservar el código VBA.
For...Next: Estructura que repite un bloque de código un número determinado de veces.
IsNumeric(): Devuelve Verdadero si un valor se puede interpretar como número.
Alt + F11: Atajo de teclado que abre el editor de VBA desde Excel.
🎬 Videos de Apoyo
Registrar, Modificar y Eliminar desde UserForm
Botón Agregar, modificar, eliminar, buscar y limpiar registros
Formulario en VBA Excel (Nuevo, Modificar, Buscar, Eliminar, Limpiar)
Formulario en Excel con VBA: Registrar, Buscar, Eliminar y Modificar
📝 Cuestionario de Evaluación
10 preguntas aleatorias del banco de 50. Calificación de 0 a 100.
Tu calificación: