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
1 SubFunction
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
1 Sub MostrarSaludo(ByVal nombre As String)
2 MsgBox "Hola, " & nombre & "!"
3 End Sub
4
5 Sub EjecutarSaludo()
6 Call MostrarSaludo("Ana")
7 Call MostrarSaludo("Carlos")
8 End Sub

ByVal vs ByRef

ByValVsRef.bas
VBA
1 Sub DoblarByVal(ByVal numero As Double)
2 numero = numero * 2
3 Debug.Print "Dentro ByVal: " & numero
4 End Sub
5
6 Sub DoblarByRef(ByRef numero As Double)
7 numero = numero * 2
8 End Sub
9
10 Sub 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
17 End Sub

Function — crear funciones personalizadas (UDF)

UDFs.bas
VBA
1 Function PrecioConIVA(ByVal precio As Double) As Double
2 PrecioConIVA = precio * 1.19
3 End Function
4
5 ' En una celda de Excel escribe:
6 ' =PrecioConIVA(B2)
7
8 Function 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
16 End 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
1 Sub LimpiarHoja()
2 Range("A1:Z100").ClearContents
3 MsgBox "Hoja limpiada."
4 End Sub
5
6 Sub PruebaLimpiar()
7 Call LimpiarHoja
8 End 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
1 Function EsPositivo(n As Double) As Boolean
2 EsPositivo = (n > 0)
3 End Function
4
5 Sub 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
13 End 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
1 Function CelsiusAFahrenheit(c As Double) As Double
2 CelsiusAFahrenheit = (c * 9 / 5) + 32
3 End 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
1 Sub 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
6 End Sub
7
8 Sub PruebaEncabezado()
9 LlenarEncabezado 5
10 End 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
1 Function Promedio3(a As Double, b As Double, c As Double) As Double
2 Promedio3 = (a + b + c) / 3
3 End Function
4
5 Sub PruebaPromedio3()
6 Dim resultado As Double
7 resultado = Promedio3(Range("A1").Value, Range("B1").Value, Range("C1").Value)
8 MsgBox "Promedio: " & resultado
9 End 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
1 Sub PrepararReporte()
2 LimpiarZona
3 EscribirEncabezados
4 MsgBox "Reporte preparado."
5 End Sub
6
7 Sub LimpiarZona()
8 Range("A1:E20").ClearContents
9 End Sub
10
11 Sub 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"
17 End 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
1 Function CalcularComision(ventas As Double, porcentaje As Double) As Double
2 CalcularComision = ventas * porcentaje
3 End 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
1 Sub AgregarIVA(ByRef precio As Double)
2 precio = precio * 1.19
3 End Sub
4
5 Sub PruebaIVA()
6 Dim p As Double
7 p = 100
8 AgregarIVA p
9 Debug.Print "Precio con IVA: " & p ' → 119
10 End 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
1 Function EsWeekend(fecha As Date) As Boolean
2 Dim dia As Integer
3 dia = Weekday(fecha)
4 EsWeekend = (dia = 1 Or dia = 7)
5 End 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
1 Sub MostrarMensaje(ByVal texto As String, Optional titulo As String = "Aviso")
2 MsgBox texto, vbInformation, titulo
3 End Sub
4
5 Sub PruebaOpcional()
6 MostrarMensaje "Operación exitosa."
7 MostrarMensaje "¡Error crítico!", "ERROR"
8 End 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
1 Function 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
9 End Function
10
11 Sub PruebaContar()
12 MsgBox "No vacías: " & ContarNoVacias(Range("A1:A20"))
13 End 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
1 Function 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
9 End 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
1 Function 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
13 End 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
1 Function 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
7 End 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
1 Function BaseImponible(precio As Double, cantidad As Integer) As Double
2 BaseImponible = precio * cantidad
3 End Function
4
5 Function CalcularIVA(base As Double) As Double
6 CalcularIVA = base * 0.19
7 End Function
8
9 Function TotalFactura(precio As Double, cantidad As Integer) As Double
10 Dim base As Double
11 base = BaseImponible(precio, cantidad)
12 TotalFactura = base + CalcularIVA(base)
13 End Function
14
15 Sub 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)
24 End Sub

Pon a prueba tus conocimientos

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