martes, 29 de abril de 2014

VBA: Variables Dim, Public, Private y Static

En definitiva hablaremos hoy del ámbito de las variables, es decir, dónde aplican nuestras variables una vez definidas. Es importante saber que el ámbito de una variable se determina en el momento en que se declara la variable.
En VBA para Excel, los tres ámbitos existentes para las variables son: Públicas, Módulo y Procedimiento.


Comenzamos por el más habitual el ámbito de Procedimiento, es decir, la variable así definida se reconoce únicamente dentro del procedimiento en el que la declaramos.
Podremos declarar una variable local de procedimiento con una instrucción Dim o Static.

Cuando definimos o declaramos una variable local con la instrucción Dim, la variable permanece en memoria sólo mientras se ejecuta el procedimiento en el que la hemos declarado, y por tanto, normalmente, cuando termina el procedimiento de ejecución, no se conservan los valores de las variables locales del procedimiento y se libera la memoria asignada a esas variables. La próxima vez que se ejecute el procedimiento, se reinicializarán todas las variables locales declaradas.

Un ejemplo de variable local DIM:

En un módulo cualquiera de nuestro proyecto de VBA insertamos los siguientes procedimientos:

Sub Local1()
   Dim X As Integer 'variable local dentro del Procedimiento
   X = 1313
   MsgBox "X tiene un valor de " & X
End Sub
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Sub Local2()
   Dim X As String 'variable local dentro del Procedimiento
   X = "Afirmativo"
   MsgBox "La respuesta ha sido " & X
End Sub


Muy importante!!: Cada variable X es independiente del otro procedimiento, sólo se reconoce la variable dentro de su propio procedimiento respectivo (Local1 ó Local2).

La otra forma de definir una variable local de Procedimiento es declarar la variable como Static. Una variable local declarada con la instrucción Static sigue existiendo todo el tiempo que se ejecuta en Visual Basic. La variable se restablece cuando se produzca cualquiera de las siguientes acciones:
- La macro genera un error de tiempo de ejecución no interceptado.
- VBA se detiene.
- Salimos de Excel.
- Cambiamos el módulo.

Un ejemplo de variable local STATIC:

En un módulo cualquiera de nuestro proyecto de VBA insertamos los siguientes procedimientos:

Sub Estatica()
   Static Acum 'variable local que retiene su valor
   'tras finalizar el procedimiento...
   num = Application.InputBox(prompt:="Introduce un valor: ", Type:=1)
   Acum = Acum + num
   MsgBox "La variable acumulada (estática) nos devuelve un valor " & Acum
End Sub


Muy Importante!!: En nuestro procedimiento Estatica, la variable 'Acum' conserva su valor cada vez que se ejecuta. Por ejemplo, la primera vez que se ejecuta el módulo, introducimos en el cuadro el valor 10, el MsgBox mostrará el valor 10 (lógicamente)... si la siguiente vez que se ejecuta el módulo, introducimos el valor 20, el MsgBox mostrará el valor de 30 (10+20...) !!.

El siguiente ámbito interesante para conocer es el de Módulo.
Una variable que es reconocida en todos los procedimientos en un módulo se denomina una variable de Módulo. Una variable de nivel de módulo está disponible para todos los procedimientos de ese mismo módulo, pero no está disponible para los procedimientos de otros módulos.
Mientras VBA se ejecuta, hasta que se modifique el módulo en el que se declara, una variable de módulo sigue existiendo.
Se pueden declarar variables de ámbito de módulo con una instrucción Dim o Private en la parte superior del módulo, encima de la primera definición de procedimiento.

En el ámbito de módulo, no hay ninguna diferencia entre Dim y Private... pero debemos tener en cuenta que no se pueden declarar variables de ámbito de módulo dentro de un Procedimiento.
En general, una recomendación, si utilizamos Private en lugar de Dim para las variables de ámbito módulo, el código será más fácil de leer esto es, si utilizamos Dim solamente para variables locales de procedimiento y Private para las variables de módulo, el ámbito de una variable determinada será más claro.
Un ejemplo de variable de módulo:

En un módulo cualquiera de nuestro proyecto de VBA insertamos los siguientes procedimientos:

'Variables A y B de ámbito Módulo
'que sirven para todos los procedimientos de este módulo
Dim A As Integer
Private B As Integer

Sub Procedimiento1()
    A = 100
    B = A + 1
End Sub

Sub Procedimiento2()
    MsgBox "A es igual a " & A
    MsgBox "B es igual a " & B
End Sub

Sub Procedimiento3()
     Dim C As Integer    'Variable local de procedimiento
     C = A + B
     MsgBox "C es igual a" & C
End Sub

Sub Procedimiento4()
     MsgBox A     'Este MsgBox muestra el valor de A
     MsgBox B     'Este MsgBox muestra el valor de B
     MsgBox C     'Este MsgBox NO muestra nada, porque C la habíamos definido como variable local de procedimiento
End Sub


Muy importante!!!: En el ejemplo siguiente, hemos comenzado declarando dos variables A y B, de ámbito de módulo (antes de todos los procedimientos!!), por tanto estarán disponibles para cualquiera de los procedimientos de dicho módulo. La tercera variable C, que se declara en la macro de Procedimienti3, es una variable local y sólo está disponible para ese procedimiento.

Tengamos en cuenta que en Procedimiento4, cuando la macro intenta utilizar la variable C, el tercer MagBox está vacíoporque C es una variable local y no está disponible en Procedimiento4, mientras que las variables A y B si lo están al tener como ámbito todo el módulo.


Finalizaremos con las variables Públicas (recordemos que eran tres los ámbitos).
Las variables públicas - Public - tienen el ámbito más amplio de todas las variables. Una variable pública es reconocida por todos los módulos del libro de trabajo activo.
Una variable pública se declara igual que una variable de ámbito de módulo, es decir, en la parte superior del módulo, encima de la primera definición de procedimiento. NO se puede declarar una variable pública dentro de un procedimiento. Siempre se declara una variable pública con una instrucción Public (podremos declarar una variable pública en cualquier módulo).

Atención por que es posible que varios módulos tengan variables públicas con el mismo nombre !!!, por tanto, para evitar confusiones y posibles errores, una buena práctica sería utilizar nombres únicos.
Un ejemplo de variable PUBLIC:

En un módulo cualquiera de nuestro proyecto de VBA insertamos el siguiente procedimiento:

Public precio As Double  'variables públicas válidas para todo el libro
Public uds As Integer
Public costes As Integer
Private factor As Double

Sub CDSales()
precio = 1.313
uds = 1000
costes = 1
factor = 1.1

MsgBox "El resultado es " & uds * (precios - (costes * factor))
End Sub


Importante!!: Las tres variables Public sirven para cualquier módulo dentro del libro, mientras que la cuarta (Pirvate factor) únicamente serviría dentro de este módulo.

25 comentarios:

  1. mejor explicado imposible!!!

    ResponderEliminar
  2. excelentemente explicado. Muy práctica y clara

    ResponderEliminar
  3. Excelente
    Muchas gracias!!!

    ResponderEliminar
  4. Muy claro. Gracias por esa labor.

    ResponderEliminar
    Respuestas
    1. Muchas gracias a todos vosotros!!
      Me alegra os resultara práctico
      Un saludo

      Eliminar
  5. Que buen trabajo hombre!
    Gracias!

    ResponderEliminar
  6. Este comentario ha sido eliminado por el autor.

    ResponderEliminar
  7. Excelente explicación
    Gracias

    ResponderEliminar
  8. hola. muy bien detallado todo.
    Sin embargo tengo una duda (no se si se pueda). Quisiera definir una constante o variable que sea reconocida por cualquier libro de macros en todos sus módulos y/o formularios ( obvio solo los de mi ordenador)

    Muchas Gracias de antemano

    ResponderEliminar
    Respuestas
    1. Hola,
      defínela como Public
      de todas formas lo importante será como la emplees (como la llames) en los diferentes libros
      Saludos

      Eliminar
  9. Gracias por el aporte, muy clara la explicación, saludos

    ResponderEliminar
  10. A eso se le llama ser acertivo, gracias Ismael por su excelente aporte.

    ResponderEliminar
  11. Explicación clarísima. Muchas gracias!
    Solo una duda: una variable definida como Public en el código de un UserForm es visible en los módulos?

    ResponderEliminar
    Respuestas
    1. Gracias,
      si, en cualquier parte del proyecto Vb (módulos o UserForm)

      ;-)
      Saludos

      Eliminar
  12. te faltan las variables Global.

    ResponderEliminar
    Respuestas
    1. Hola
      creo que nunca he definido una variable en ámbito Global, ya que en todo caso sería equivalente a una Public
      Salvo comentario en contra
      Saludos

      Eliminar

Nota: solo los miembros de este blog pueden publicar comentarios.