🗂️ 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 Código copiable Simulador Diccionario Quiz 10/50

📖 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:

Encabezados de la hoja Productos
Columna Encabezado Contenido esperado
A1IDNúmero consecutivo, lo asigna el código automáticamente
B1NombreTexto
C1DescripcionTexto
D1IdCategoriaNúmero (referencia al ID de una categoría)
E1EntradasNúmero (unidades que han ingresado)
F1SalidasNúmero (unidades que han salido)
G1CantidadNú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.

  1. Con el formulario seleccionado, abre Propiedades (F4) y cambia su (Name) a frmProductos.
  2. Arrastra 7 TextBox y 5 CommandButton al formulario.
  3. Renombra cada control (propiedad (Name)) exactamente como en la tabla — el código de los siguientes pasos depende de estos nombres.
Controles del formulario
Tipo Name Caption / uso
TextBoxtxtIDID del registro (buscar, actualizar, eliminar)
TextBoxtxtNombreNombre del producto
TextBoxtxtDescripcionDescripción del producto
TextBoxtxtIdCategoriaID de la categoría a la que pertenece
TextBoxtxtEntradasUnidades que han entrado (compras/ingresos)
TextBoxtxtSalidasUnidades que han salido (ventas/consumos)
TextBoxtxtCantidadExistencia actual en inventario
CommandButtonbtnCrearCaption: "Crear"
CommandButtonbtnBuscarCaption: "Buscar"
CommandButtonbtnActualizarCaption: "Actualizar"
CommandButtonbtnEliminarCaption: "Eliminar"
CommandButtonbtnLimpiarCaption: "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:

Private Function BuscarFilaPorID(ws As Worksheet, id As Long) As Long Dim ultimaFila As Long Dim i As Long ultimaFila = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row For i = 2 To ultimaFila If ws.Cells(i, 1).Value = id Then BuscarFilaPorID = i Exit Function End If Next i BuscarFilaPorID = 0 End Function

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:

Private Sub LimpiarCampos() Me.txtID.Value = "" Me.txtNombre.Value = "" Me.txtDescripcion.Value = "" Me.txtIdCategoria.Value = "" Me.txtEntradas.Value = "" Me.txtSalidas.Value = "" Me.txtCantidad.Value = "" Me.txtNombre.SetFocus End Sub

💡 ¿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.

Private Sub btnCrear_Click() Dim ws As Worksheet Dim nuevaFila As Long Set ws = ThisWorkbook.Sheets("Productos") If Trim(Me.txtNombre.Value) = "" Then MsgBox "Escribe un nombre antes de guardar.", vbExclamation Exit Sub End If nuevaFila = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row + 1 ws.Cells(nuevaFila, 1).Value = nuevaFila - 1 ws.Cells(nuevaFila, 2).Value = Me.txtNombre.Value ws.Cells(nuevaFila, 3).Value = Me.txtDescripcion.Value ws.Cells(nuevaFila, 4).Value = Val(Me.txtIdCategoria.Value) ws.Cells(nuevaFila, 5).Value = Val(Me.txtEntradas.Value) ws.Cells(nuevaFila, 6).Value = Val(Me.txtSalidas.Value) ws.Cells(nuevaFila, 7).Value = Val(Me.txtCantidad.Value) MsgBox "Registro creado correctamente.", vbInformation Call LimpiarCampos End Sub
  • Set ws = ThisWorkbook.Sheets("Productos") — apunta ws a 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.

Private Sub btnBuscar_Click() Dim ws As Worksheet Dim fila As Long Set ws = ThisWorkbook.Sheets("Productos") If Trim(Me.txtID.Value) = "" Then MsgBox "Escribe el ID que quieres buscar.", vbExclamation Exit Sub End If fila = BuscarFilaPorID(ws, CLng(Me.txtID.Value)) If fila = 0 Then MsgBox "No existe ningún registro con ese ID.", vbExclamation Exit Sub End If Me.txtNombre.Value = ws.Cells(fila, 2).Value Me.txtDescripcion.Value = ws.Cells(fila, 3).Value Me.txtIdCategoria.Value = ws.Cells(fila, 4).Value Me.txtEntradas.Value = ws.Cells(fila, 5).Value Me.txtSalidas.Value = ws.Cells(fila, 6).Value Me.txtCantidad.Value = ws.Cells(fila, 7).Value End Sub

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

Private Sub btnActualizar_Click() Dim ws As Worksheet Dim fila As Long Set ws = ThisWorkbook.Sheets("Productos") If Trim(Me.txtID.Value) = "" Then MsgBox "Primero busca un registro por su ID.", vbExclamation Exit Sub End If fila = BuscarFilaPorID(ws, CLng(Me.txtID.Value)) If fila = 0 Then MsgBox "Ese ID no existe. No hay nada que actualizar.", vbExclamation Exit Sub End If ws.Cells(fila, 2).Value = Me.txtNombre.Value ws.Cells(fila, 3).Value = Me.txtDescripcion.Value ws.Cells(fila, 4).Value = Val(Me.txtIdCategoria.Value) ws.Cells(fila, 5).Value = Val(Me.txtEntradas.Value) ws.Cells(fila, 6).Value = Val(Me.txtSalidas.Value) ws.Cells(fila, 7).Value = Val(Me.txtCantidad.Value) MsgBox "Registro actualizado.", vbInformation End Sub

⚠️ 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.

Private Sub btnEliminar_Click() Dim ws As Worksheet Dim fila As Long Dim respuesta As VbMsgBoxResult Set ws = ThisWorkbook.Sheets("Productos") fila = BuscarFilaPorID(ws, CLng(Me.txtID.Value)) If fila = 0 Then MsgBox "Ese ID no existe.", vbExclamation Exit Sub End If respuesta = MsgBox("¿Seguro que quieres eliminar este registro?", vbYesNo + vbQuestion) If respuesta = vbYes Then ws.Rows(fila).Delete MsgBox "Registro eliminado.", vbInformation Call LimpiarCampos End If End Sub

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

Private Sub btnLimpiar_Click() Call LimpiarCampos End Sub

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:

Sub MostrarFormulario() frmProductos.Show End Sub

💡 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 duplicadasSe llamó a Crear en vez de Actualizar sobre un registro existente
Las macros no aparecen al reabrir el archivoSe guardó como .xlsx en vez de .xlsm (Libro habilitado para macros)
IdCategoria/Entradas/Salidas/Cantidad quedan como textoSe 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)

txtNombreSilla nórdica
txtDescripcionSilla de comedor en roble
txtIdCategoria3
txtEntradas20
txtSalidas16
txtCantidad4

Hoja "Productos"

IDNombreDescripcionIdCategoriaEntradasSalidasCantidad
1Lámpara de pieLámpara de lectura, base de madera51257

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