Café y Código

5. Subrutinas y Funciones Propias

En esta lección aprenderás a:

  • Distinguir Sub (sin retorno) de Function (con retorno).
  • Pasar parámetros con ByVal y ByRef.
  • Llamar un Sub desde otro procedimiento.
  • Crear funciones personalizadas (UDF) usables directamente en celdas.

Sub vs Function

Vista tipo Excel: la primera fila muestra las letras de columna; la primera columna muestra los números de fila. En las celdas con fórmula (=...), cada referencia lleva un color distinto. Clic en la referencia: resalta solo esa celda. Clic en el resto de la celda (por ejemplo el = o los operadores): resalta todas las celdas citadas. Repetir el mismo gesto sobre lo ya resaltado lo oculta.

Diferencias clave entre Sub y FunctionResumen

Una Sub automatiza acciones. Una Function calcula y devuelve un resultado.

ABC
1SubFunction
2Devuelve un valorNo
3Se puede usar en celdas de ExcelNoSí (UDF)
4Se puede llamar desde código
5Aparece en Alt+F8 (lista de macros)No
6Sintaxis de cierreEnd SubEnd Function

Sub con parámetros — ByVal

Saludos.bas
VBA
1Sub MostrarSaludo(ByVal nombre As String)
2 MsgBox "Hola, " & nombre & "!"
3End Sub
4
5Sub EjecutarSaludo()
6 Call MostrarSaludo("Ana")
7 Call MostrarSaludo("Carlos")
8End Sub

ByVal vs ByRef

ByValVsRef.bas
VBA
1Sub DoblarByVal(ByVal numero As Double)
2 numero = numero * 2
3 Debug.Print "Dentro ByVal: " & numero
4End Sub
5
6Sub DoblarByRef(ByRef numero As Double)
7 numero = numero * 2
8End Sub
9
10Sub Prueba()
11 Dim x As Double
12 x = 5
13 DoblarByVal x
14 Debug.Print "ByVal — x sigue siendo: " & x ' → 5
15 DoblarByRef x
16 Debug.Print "ByRef — x ahora es: " & x ' → 10
17End Sub

Function — crear funciones personalizadas (UDF)

UDFs.bas
VBA
1Function PrecioConIVA(ByVal precio As Double) As Double
2 PrecioConIVA = precio * 1.19
3End Function
4
5' En una celda de Excel escribe:
6' =PrecioConIVA(B2)
7
8Function ClasificarEdad(ByVal edad As Integer) As String
9 If edad < 18 Then
10 ClasificarEdad = "Menor de edad"
11 ElseIf edad < 65 Then
12 ClasificarEdad = "Adulto"
13 Else
14 ClasificarEdad = "Adulto mayor"
15 End If
16End Function

Practica en Excel

Abre Excel (o copia los datos con el botón de la tabla), sigue los pasos y comprueba el resultado en tu hoja.

  1. Crea MostrarSaludo() y llámala desde EjecutarSaludo() con dos nombres distintos.
  2. Ejecuta la Sub Prueba() y verifica en la ventana Inmediata la diferencia entre ByVal y ByRef.
  3. Escribe PrecioConIVA() en el módulo y úsala desde una celda con =PrecioConIVA(1000).
  4. Crea ClasificarEdad() y aplícala en una columna de edades.

Ejercicios de práctica

Ejercicio 1 — Sub que limpia un rango

Crea una Sub LimpiarHoja que borre el contenido de A1:Z100 de la hoja activa. Llámala desde otra Sub para probarla.

Ver solución sugerida
LimpiarHoja.bas
VBA
1Sub LimpiarHoja()
2 Range("A1:Z100").ClearContents
3 MsgBox "Hoja limpiada."
4End Sub
5
6Sub PruebaLimpiar()
7 Call LimpiarHoja
8End Sub

Ejercicio 2 — Function: es positivo?

Crea una Function EsPositivo(n As Double) As Boolean que devuelva True si el número es mayor que 0. Úsala en una Sub que lea A1 y muestre el resultado con MsgBox.

Ver solución sugerida
EsPositivo.bas
VBA
1Function EsPositivo(n As Double) As Boolean
2 EsPositivo = (n > 0)
3End Function
4
5Sub PruebaEsPositivo()
6 Dim val As Double
7 val = Range("A1").Value
8 If EsPositivo(val) Then
9 MsgBox val & " es positivo."
10 Else
11 MsgBox val & " NO es positivo."
12 End If
13End Sub

Ejercicio 3 — UDF: Celsius a Fahrenheit

Crea una UDF CelsiusAFahrenheit(c As Double) As Double. La fórmula es (c × 9/5) + 32. Úsala en una celda con =CelsiusAFahrenheit(A1).

Ver solución sugerida
Temperatura.bas
VBA
1Function CelsiusAFahrenheit(c As Double) As Double
2 CelsiusAFahrenheit = (c * 9 / 5) + 32
3End Function

Ejercicio 4 — Sub con parámetro de encabezado

Crea una Sub LlenarEncabezado(ByVal columnas As Integer) que escriba "Columna 1", "Columna 2", … hasta el número de columnas indicado, en la fila 1. Llámala con LlenarEncabezado 5.

Ver solución sugerida
LlenarEncabezado.bas
VBA
1Sub LlenarEncabezado(ByVal columnas As Integer)
2 Dim i As Integer
3 For i = 1 To columnas
4 Cells(1, i).Value = "Columna " & i
5 Next i
6End Sub
7
8Sub PruebaEncabezado()
9 LlenarEncabezado 5
10End Sub

Ejercicio 5 — Function: promedio de tres

Crea una Function Promedio3(a As Double, b As Double, c As Double) As Double y úsala en una Sub que lea tres celdas y muestre el promedio.

Ver solución sugerida
Promedio3.bas
VBA
1Function Promedio3(a As Double, b As Double, c As Double) As Double
2 Promedio3 = (a + b + c) / 3
3End Function
4
5Sub PruebaPromedio3()
6 Dim resultado As Double
7 resultado = Promedio3(Range("A1").Value, Range("B1").Value, Range("C1").Value)
8 MsgBox "Promedio: " & resultado
9End Sub

Ejercicio 6 — Sub organizada en dos partes ⭐⭐

Crea una Sub principal PrepararReporte que llame a dos Sub auxiliares: LimpiarZona (borra A1:E20) y EscribirEncabezados (escribe títulos en la fila 1). Organiza el código en tres procedimientos separados.

Ver solución sugerida
Reporte.bas
VBA
1Sub PrepararReporte()
2 LimpiarZona
3 EscribirEncabezados
4 MsgBox "Reporte preparado."
5End Sub
6
7Sub LimpiarZona()
8 Range("A1:E20").ClearContents
9End Sub
10
11Sub EscribirEncabezados()
12 Range("A1").Value = "Producto"
13 Range("B1").Value = "Precio"
14 Range("C1").Value = "Cantidad"
15 Range("D1").Value = "Subtotal"
16 Range("E1").Value = "Con IVA"
17End Sub

Ejercicio 7 — UDF: comisión de ventas ⭐⭐

Crea una UDF CalcularComision(ventas As Double, porcentaje As Double) As Double. Úsala en celdas con =CalcularComision(A1, 0.08) para calcular el 8% de comisión.

Ver solución sugerida
Comision.bas
VBA
1Function CalcularComision(ventas As Double, porcentaje As Double) As Double
2 CalcularComision = ventas * porcentaje
3End Function

Ejercicio 8 — ByRef en práctica ⭐⭐

Crea una Sub AgregarIVA(ByRef precio As Double) que multiplique el precio por 1.19 modificando la variable original. Comprueba que después de llamarla, la variable del llamador tiene el nuevo valor.

Ver solución sugerida
AgregarIVA.bas
VBA
1Sub AgregarIVA(ByRef precio As Double)
2 precio = precio * 1.19
3End Sub
4
5Sub PruebaIVA()
6 Dim p As Double
7 p = 100
8 AgregarIVA p
9 Debug.Print "Precio con IVA: " & p ' → 119
10End Sub

Ejercicio 9 — UDF: ¿Es fin de semana? ⭐⭐

Crea una UDF EsWeekend(fecha As Date) As Boolean que devuelva True si la fecha cae en sábado (7) o domingo (1) usando Weekday(). Úsala en una celda.

Ver solución sugerida
EsWeekend.bas
VBA
1Function EsWeekend(fecha As Date) As Boolean
2 Dim dia As Integer
3 dia = Weekday(fecha)
4 EsWeekend = (dia = 1 Or dia = 7)
5End Function

Ejercicio 10 — Parámetro opcional ⭐⭐

Crea una Sub MostrarMensaje(ByVal texto As String, Optional titulo As String = "Aviso"). Si se pasa el segundo argumento usa ese título; si no, usa "Aviso" como predeterminado. Pruébala con y sin el segundo argumento.

Ver solución sugerida
MensajeOpcional.bas
VBA
1Sub MostrarMensaje(ByVal texto As String, Optional titulo As String = "Aviso")
2 MsgBox texto, vbInformation, titulo
3End Sub
4
5Sub PruebaOpcional()
6 MostrarMensaje "Operación exitosa."
7 MostrarMensaje "¡Error crítico!", "ERROR"
8End Sub

Ejercicio 11 — Function que cuenta no vacías ⭐⭐⭐

Crea una Function ContarNoVacias(rango As Range) As Integer que cuente las celdas con contenido en el rango dado. Úsala en una Sub pasando Range("A1:A20").

Ver solución sugerida
ContarNoVacias.bas
VBA
1Function ContarNoVacias(rango As Range) As Integer
2 Dim celda As Range
3 Dim c As Integer
4 c = 0
5 For Each celda In rango
6 If celda.Value <> "" Then c = c + 1
7 Next celda
8 ContarNoVacias = c
9End Function
10
11Sub PruebaContar()
12 MsgBox "No vacías: " & ContarNoVacias(Range("A1:A20"))
13End Sub

Ejercicio 12 — UDF: clasificar venta ⭐⭐⭐

Crea una UDF ClasificarVenta(monto As Double) As String que devuelva "Baja" (menor de 1000), "Media" (1000–9999) o "Alta" (10000 o más). Aplícala en una columna de montos.

Ver solución sugerida
ClasificarVenta.bas
VBA
1Function ClasificarVenta(monto As Double) As String
2 If monto < 1000 Then
3 ClasificarVenta = "Baja"
4 ElseIf monto < 10000 Then
5 ClasificarVenta = "Media"
6 Else
7 ClasificarVenta = "Alta"
8 End If
9End Function

Ejercicio 13 — Extraer solo letras ⭐⭐⭐

Crea una Function SoloLetras(texto As String) As String que recorra el texto carácter por carácter con Mid() y devuelva solo las letras (A-Z, a-z) eliminando números y espacios.

Ver solución sugerida
SoloLetras.bas
VBA
1Function SoloLetras(texto As String) As String
2 Dim resultado As String
3 Dim i As Integer
4 Dim c As String
5 resultado = ""
6 For i = 1 To Len(texto)
7 c = Mid(texto, i, 1)
8 If (c >= "A" And c <= "Z") Or (c >= "a" And c <= "z") Then
9 resultado = resultado & c
10 End If
11 Next i
12 SoloLetras = resultado
13End Function

Ejercicio 14 — Exit Function ⭐⭐⭐

Crea una Function DividirSeguro(a As Double, b As Double) As Variant que devuelva el resultado de a/b. Si b es 0, usa Exit Function después de asignar DividirSeguro = "Error: división por cero".

Ver solución sugerida
DividirSeguro.bas
VBA
1Function DividirSeguro(a As Double, b As Double) As Variant
2 If b = 0 Then
3 DividirSeguro = "Error: división por cero"
4 Exit Function
5 End If
6 DividirSeguro = a / b
7End Function

Ejercicio 15 — Pipeline de funciones ⭐⭐⭐

Crea tres funciones: BaseImponible(precio, cantidad), CalcularIVA(base) y TotalFactura(precio, cantidad) que llame a las dos anteriores. Escribe en celdas A1=precio, B1=cantidad y ejecuta una Sub que llene C1=base, D1=IVA y E1=total.

Ver solución sugerida
Pipeline.bas
VBA
1Function BaseImponible(precio As Double, cantidad As Integer) As Double
2 BaseImponible = precio * cantidad
3End Function
4
5Function CalcularIVA(base As Double) As Double
6 CalcularIVA = base * 0.19
7End Function
8
9Function TotalFactura(precio As Double, cantidad As Integer) As Double
10 Dim base As Double
11 base = BaseImponible(precio, cantidad)
12 TotalFactura = base + CalcularIVA(base)
13End Function
14
15Sub LlenarFactura()
16 Dim precio As Double
17 Dim cantidad As Integer
18 precio = Range("A1").Value
19 cantidad = CInt(Range("B1").Value)
20
21 Range("C1").Value = BaseImponible(precio, cantidad)
22 Range("D1").Value = CalcularIVA(BaseImponible(precio, cantidad))
23 Range("E1").Value = TotalFactura(precio, cantidad)
24End Sub

Pon a prueba tus conocimientos

Ko-fi
Donaciones
Apoyá cafeycodigo con un café en Ko-fi. Colaboradores: insignia, muro y zona exclusiva.