![]() |
||||||
|
|
||||||
Usando variables en VBA
Variables de objetoHasta ahora hemos visto como dimensionar y declarar variables de tipos simples (texto, números y fecha), pero, ¿qué debemos hacer si deseamos declarar variables que contengan objetos? Pues prácticamente lo mismo: declaramos la variable para reservar un espacio en memoria que la contenga, y ya podemos acceder al objeto a través de esa variable. Lo que hay que tener en cuenta es que, además de declarar la variable para inicializarla, debemos inicializar el objeto para poder trabajar con él:
Usar una variable que haga referencia a un objeto
Sub DeclararObjeto() Dim l As Long Primero declaramos la variable Dim obj As Collection Después inicializamos el objeto Set obj = New Collection Y ya podemos trabajar con la variable obj.Add "Primer elemento", "uno" obj.Add "Segundo elemento", "dos" obj.Add "Tercer elemento", "tres" For l = 1 To obj.Count Debug.Print "Elemento " & l & " en la colección: " & obj(l) Next Do While obj.Count > 0 obj.Remove 1 Loop End Sub En el ejemplo, hemos dimensionado la variable En VBA, las 2 líneas para declarar la variable e inicializar el objeto, las podemos unir en una sola:
Dim obj As New Collection
Pero este método no hace exactamente lo mismo: según Microsoft, utilizar Destruir los objetosLas variables de tipos simples no las destruíamos, ni indicábamos que fueran eliminadas de la memoria, pero con las variables de objetos sí que lo podemos hacer. Si indicamos al final del procedimiento anterior:
Set obj = Nothing
Estamos indicando que se elimine la variable y el objeto al que apunta. Pero, ¿es realmente necesario? La respuesta, como muchas cosas en esta vida, depende del contexto. En nuestro ejemplo, creamos una variable local. Y al ser una variable local, ésta será creada y destruida cada vez que usemos o ejecutemos el procedimiento, con lo que no necesitamos destruir la variable: VBA se encargará de destruirla cuando salga del procedimiento. Pero no ocurre lo mismo con las variables públicas o privadas de un módulo estándar o módulo de clase. En estos casos, sí que debemos destruirlas, o permanecerán cargadas, como mínimo, mientras tengamos abierta la base de datos y, en según que casos, hasta después de haber cerrado la base de datos. Esto conlleva una pérdida de memoria y de rendimiento, que a l@s usuari@s de nuestra base de datos nos les gustará lo más mínimo. Mucho más importante que pensar en destruir los objetos es el cerrarlos, que aunque parezca lo mismo, no lo es. Por ejemplo, podemos tener dos objetos de la librería de DAO:
Sub ActualizarTablaExterna(valor1 As String, valor2 As String, valor3 As Integer)
'Dimensionamos los objetos Dim dbs As DAO.Database Dim rst As DAO.Recordset 'A estos objetos no los inicializamos con New, 'se crean a partir de métodos de otros objetos Set dbs = Workspaces(0).OpenDatabase("P:\Test\test.mdb") Set rst = dbs.OpenRecordset("SELECT campo1, campo2, campo3 FROM TablaPruebas") 'Agregamos un registro With rst .AddNew .Fields("campo1") = valor1 .Fields("campo2") = valor2 .Fields("campo3") = valor3 .Update End With 'Ahora hacemos lo más importante, cerrar: rst.Close dbs.Close End Sub Al cerrar los objetos con sus métodos Las ventajas de cerrar los objetos son muchas, pero hay objetos que no se pueden cerrar. ¿Por qué? Porque no disponen de un método para cerrarlos. Este tipo de objetos suelen ser más sencillos, o no acceden a otros objetos o archivos de la base de datos, con lo que al destruirlos, se elimina el objeto y todas sus referencias. Los objetos son tipos por referenciaOtra cuestión sobre las variables de objeto, es que no mantienen sus datos internamente, al igual que ocurría con las variables de tipos simples. Si probamos el siguiente código:
Sub ObjetosPorRef()
'Dimensionamos los tipos simples Dim int1 As Integer Dim int2 As Integer 'Damos valor a las variables int1 = 10 'A la segunda variable, le damos el 'valor de la primera int2 = int1 'Y la modificamos int2 = 60 'Y la primera variable no ha cambiado Debug.Print "int1 tiene el valor " & int1 'Dimensionamos los objetos Dim clase1 As ClaseObjetos Dim clase2 As ClaseObjetos 'Y los inicializamos Set clase1 = New ClaseObjetos 'Damos un valor al primer objeto clase1.Dato = "Pepe" 'Al segundo objeto, le asignamos 'lo que tiene el primero Set clase2 = clase1 'Y modificamos el segundo objeto clase2.Dato = "Juan" 'Pero el primero también ha sido modificado Debug.Print "Clase1 tiene el valor " & clase1.Dato End Sub Suponiendo que hemos creado un módulo de clase de nombre ClaseObjetos en la misma base de datos con el siguiente código:
Option Compare Database
Option Explicit Public Dato As String Veremos que la variable Esto ocurre porque las variables de tipos simples, como En cambio, las variables de objeto almacenan una dirección de memoria, donde se encuentran las propiedades, funciones y métodos de ese objeto que se ha creado. Y cuando asignamos a una variable de clase otra variable de clase u objeto, le estamos dando la dirección de memoria que tiene guardada la segunda variable, con lo que las 2 variables acceden directamente al mismo objeto físico. Es decir, funciona de la misma forma que si a un parámetro de una función le asignamos el valor Hay objetos que permiten asignarlos mediante métodos, sin que apunten distintas variables a la misma posición de memoria. Por ejemplo, el objeto |
||||||
|
2008 Patxi Sanz Libro de visitas |