Beruflich Dokumente
Kultur Dokumente
Piensa Objetivamente
En esta ocasión vamos a tratar con las colecciones y las colecciones de colecciones,
también veremos cómo avisar al programa que use nuestros objetos de que ha
ocurrido algo, esto lo conseguiremos mediante los eventos.
Para ver todo esto, vamos a crear una pequeña utilidad que nos permita examinar el
contenido de una unidad de disco, por un lado se guardarán los directorios con sus
respectivos ficheros y por otro todos los ficheros con nombres diferentes, para, entre
otras cosas, saber en cuantos directorios existe un fichero en concreto. Como la
cantidad de ficheros puede ser elevada, a la hora de "examinar" la unidad, se hará en
un sólo nivel de directorios (realmente dos, el de inicio y cada uno de los que cuelgan
de este) o bien recorriendo todos y cada uno de los directorios de la unidad
examinada.
Toda esta información se guardará en unas colecciones mantenidas por una clase y
se mostrarán en dos ComboBox, uno para los nombres de los ficheros y otro para los
nombres de los directorios. Al seleccionar un fichero, se mostrarán todos los
directorios en los que se encuentra y lo mismo ocurrirá cuando se seleccione un
directorio: se mostrarán todos los ficheros que contiene.
Para realizar esta tarea vamos a usar una clase básica en la que se almacenará un
nombre, que será, según el contexto en el que se use, el fichero o el directorio.
También tendremos una colección en la que almacenaremos todos los ficheros de un
directorio en concreto.
Por último, otra clase mantendrá a su vez una colección de estos directorios y de
todos los ficheros, con nombres diferentes, que se encuentren en esa unidad. Esta
clase también será la que se encargue de explorar la unidad y tendrá unos métodos
que nos permitirán mostrar los ficheros de un directorio y todos los directorios en los
que se encuentra un fichero en concreto. Además nos avisará, por medio de eventos
cuando se encuentre un nuevo directorio o un nuevo fichero.
Para usar la clase, al usar eventos, tendremos que crearla de esta forma:
Dim WithEvents tDrive As cDrive
De esta forma, se creará una entrada en la lista de objetos del form en los que se
podrá seleccionar cualquiera de los eventos, para hacer algo en particular. En nuestro
caso, se producirá un evento cada vez que se encuentre un nuevo directorio y
también cuando se encuentre un nuevo nombre de fichero (sin repetirse), cuando uno
de estos eventos se produzca, añadiremos a los combos el nombre del directorio o
fichero hallado.
Vamos a ver el código usado en estos eventos:
Si sólo queremos evaluar un nivel y sólo los ficheros normales, podríamos usar los
valores por defecto:
tDrive.FillDirs Text1
Este método simplemente procesará cada uno de los directorios y cada vez que
encuentre un nuevo fichero, llamará al método Add de esta clase que se encargará de
incluir en las colecciones correspondientes los valores que ha recibido, éste método
es bastante simple y este es el código empleado:
End Sub
Como podrás adivinar, el trabajo "duro" está en lo que se haga al emplear Dirs o Files,
pero esa parte vamos a dejarla para dentro de un poco, antes vamos a ver cada una
de las piezas de este puzzle.
Veamos también cómo llamar a los métodos creados para mostrar los directorios en
los que se encuentra un fichero en concreto y para mostrar todos los ficheros de un
directorio.
En el form de ejemplo se hace al seleccionar un elemento del combo destinado para
ello.
Por ejemplo cuando seleccionamos un fichero del Combo1:
'-------------------------------------------------------
-----------
'cFile.cls
(22/May/98)
'Clase básica para almacenar un nombre
'
'©Guillermo 'guille' Som, 1998
'-------------------------------------------------------
-----------
Option Explicit
Esta es una colección que contendrá objetos del tipo cFile, esta sería la forma de usar
una colección personalizada, aunque he omitido el uso de los métodos habituales
como Add, Count y Remove, no sería una tarea demasiado complicada, ya que
simplemente tendríamos que delegar en la colección privada, después mostraré cómo
se tendrían que implementar estos métodos, pero que en el ejemplo no he usado, ya
que no serán necesarios.
Esta clase/colección tiene una propiedad: Path que será el nombre del directorio de
los ficheros que contiene, es decir en esta clase se guardarán todos los ficheros de un
directorio específico.
El método/propiedad que se encarga de almacenar los distintos ficheros será Item,
que será la propiedad por defecto.
Para hacer que una propiedad sea la que se use por defecto, hay que seleccionar esa
propiedad y en el menú Herramientas, seleccionar la opción Atributos del
procedimiento. Nos mostrará un cuadro de diálogo en el cual habrá que pulsar en el
botón Avanzados y en la lista Id. del procedimiento, seleccionar Predeterminado.
Otro método que tendrá esta colección, como toda buena colección, es un método
NewEnum, el cual nos permitirá recorrer el contenido de la colección usando For Each
... Next. Para ello este método debe estar oculto y el Id. del procedimiento tener un
valor -4 (menos cuatro)
'-------------------------------------------------------
-----------
'cFiles.cls
(22/May/98)
'Clase colección para almacenar objetos del tipo cFile
'
'©Guillermo 'guille' Som, 1998
'-------------------------------------------------------
-----------
Option Explicit
End Function
Cada vez que una clase se crea, se produce el evento Class_Initialize y ahí será un
buen sitio para hacer las asignaciones por defecto que necesitemos, en este caso,
sólo se crea la colección que contendrá los ficheros.
Igualmente cuando el objeto se destruye, se produce Class_Terminate y en ese sitio
es dónde destruimos la colección.
Esta es la clase que maneja cada uno de los datos y la que se encargará de proveer
de Eventos y métodos para mostrar los ficheros y directorios contenidos en las
colecciones.
Vamos a ver el código completo y después entraremos en los pequeños detalles que
sean necesarios.
'-------------------------------------------------------
-----------
'cDrive
(22/May/98)
'Clase para mantener colecciones de ficheros y
directorios
'
'©Guillermo 'guille' Som, 1998
'-------------------------------------------------------
-----------
Option Explicit
Option Compare Text
Dirs(sDir)(sFile).Name = sFile
'Añadir a la colección de ficheros
Call Files(sFile)
End Sub
Public Function Files(Optional ByVal Index As Variant)
As Variant
'Este método devolverá una colección de los ficheros
'o el item indicado
'
'Si no existe, se añade
'
On Local Error Resume Next
If IsMissing(Index) Then
Set Files = colFiles
Else
Files = colFiles.Item(Index)
If Err Then
colFiles.Add Index, Index
Files = Index
RaiseEvent NewFile(Index)
End If
End If
Err = 0
End Function
If IsMissing(Index) Then
'Devolver la colección
Set Dirs = colDirs
Else
Set Dirs = colDirs.Item(Index)
If Err Then
tFiles.Path = Index
colDirs.Add tFiles, Index
Set Dirs = tFiles
RaiseEvent NewDir(Index)
End If
End If
Err = 0
End Function
Screen.MousePointer = vbArrowHourglass
aList.Clear
'
For Each tFile In colDirs(sDir)
aList.AddItem tFile.Name
Next
ExitShowDirs:
Screen.MousePointer = vbDefault
Err = 0
End Sub
Screen.MousePointer = vbArrowHourglass
aList.Clear
For Each tFiles In colDirs
For Each tFile In tFiles
If tFile.Name = sFile Then
aList.AddItem tFiles.Path
Exit For
End If
Next
Next
ExitShowFiles:
Screen.MousePointer = vbDefault
Err = 0
End Sub
DoEvents
If Cancel Then
Exit Sub
End If
sDir = NewDrive
If Right$(sDir, 1) <> "\" Then
sDir = sDir & "\"
End If
If Len(FirstDir) = 0 Then
FirstDir = sDir
End If
Dirs.Add sDir
sFile = Dir$(sDir & "*.*", vbDirectory)
Do While Len(sFile)
If (GetAttr(sDir & sFile) And vbDirectory) =
vbDirectory Then
If sFile <> "." And sFile <> ".." Then
Dirs.Add sFile
End If
End If
sFile = Dir$
Loop
For i = 1 To Dirs.Count
sFile = ""
sDir = Dirs(i)
If Right$(sDir, 1) <> "\" Then
sDir = sDir & "\"
End If
If i = 1 Then
If FirstDir = sDir Then
sFile = Dir$(sDir & "*.*", Atributos)
End If
Else
If AllLevels Then
FillDirs NewDrive & sDir, Atributos,
AllLevels
End If
sFile = Dir$(NewDrive & sDir & "*.*",
Atributos)
sDir = NewDrive & sDir
End If
Do While Len(sFile)
Me.Add sDir, sFile
DoEvents
If Cancel Then
Exit For
End If
sFile = Dir$
Loop
Next
End Sub
Aunque esta forma de uso tiene sus inconvenientes, es la forma más simple de
"manipular" los elementos de una colección, al menos desde el enfoque que se le ha
dado de sencillez a la hora de asignar nuevos elementos.
'
Option Explicit
Option Compare Text
Dirs(sDir)(sFile).Name = sFile
'Añadir a la colección de ficheros
Files(sFile).Name = sFile
End Sub
Las propiedades Dirs y Files se han simplificado al máximo... más simples: ¡imposible!
Pero...
¿Cuando se producen los eventos?
Bien, ahora sólo tendremos que cambiar la declaración que tenemos en cDrive para
acceder a esta colección, por esta otra:
Private WithEvents colFiles As cFiles
Y como hemos visto, tendremos un nuevo "objeto" colFiles con un evento NewItem, el
cual usaremos para lanzar el evento que indique que se ha añadido un nuevo fichero:
Por último veamos la nueva clase cDirs al completo, (he dejado algunos métodos
comentados por si se quieren implementar)
'-------------------------------------------------------
-----------
'cDirs colección de objetos del tipo cFiles
(25/May/98)
'
'©Guillermo 'guille' Som, 1998
'-------------------------------------------------------
-----------
Option Explicit
End Function
Err = 0
End Function
Realmente esta última clase la tengo como "plantilla" para crear nuevas
clases/colecciones, sólo necesito cambiar el tipo de objeto que se añade a la
colección y de esta forma me sirve de forma genérica.