Nota:
Te aclaro que todo lo tratado en esta página es referente a las versiones anteriores a .NET, y en la mayoría de los casos fueron escritos con Visual Basic 4.0, por tanto es posible que tengas que revisar el código para usarlo con Visual Basic 6.0 ó 5.0, pero no serán válidos para Visual Basic .NET (2002) y posteriores.
No es, como quieren pintarla, la panacea de la programación ni tampoco un ogro al que haya que temer. Es como usar "tipos declarados", (el TYPE que se empezó a usar con QuickBasic 4.0), pero con "valor añadido".
Más de uno se habrá frustrado al intentar "meterle" mano a esto de las clases, además con los ejemplos que he visto por ahí, (que sólo los entienden los que ya saben), no se aclaran bien las cosas.
No pretendo enseñar a nadie, sólo contaros lo que sé, o parte de lo que sé, para que os resulte fácil y, espero, sencillo convivir con las clases en VB.Veámoslo con ejemplos:
Contenido:
- Usarla en lugar de un array (Dic/97)
- En el programa gsExecute hay otro ejemplo
- Crear una librería OLE
- Un poco más de clase
- Y más todavía, con y sin librería OLE (Librería OLE y ejemplos de cómo usar los objetos expuestos)
- Servidor OLE para obtener los recursos del Sistema
- Un servidor OLE Outprocess: Averiguar si una aplicación se está ejecutando.
- Clase para simular el StatusBar (de forma simple)
- Una clase para saber los directorios del Sistema (Windows, System, Archivos de Programa, Menú Inicio, etc.)
- Más artículos sobre los objetos: publicados originalmente en VB Online edición USA (14/Ago/98)
Objetos en Visual Basic
Objetos en Visual Basic: Piensa objetivamente- Los artículos publicados en Algoritmo sobre Objetos en Visual Basic
- El tercer (y por ahora último) artículo publicado en Algoritmo sobre Objetos en VB
- Una clase para manipular el registro del Sistema
- Colaboración de Luis Sanz: Ponga una clase en su vida
- cGetTimer: una clase para calcular periodos pequeños de tiempo
- Nueva colaboración de Luis Sanz: Ponga una clase en su vida (dos)
- Simular la herencia con el Visual Basic
- Notas sobre la compatibilidad binaria en componentes ActiveX
- Copiar objetos en Visual Basic (clonar objetos) (24/Ago/99)
- SelDir: Diálogo para seleccionar Directorios y/o archivos
- gsSelDir: Control para seleccionar Directorios
- gsSelDirFile: Control para seleccionar Directorios y Archivos (gsSelDirFile)
- Sobre la creación de componentes ActiveX/COM (entrega 47 del curso básico) (28/Feb/2004)
- Repaso rápido sobre las clases (entrega 47 del curso básico) (28/Feb/2004)
Más ejemplos relacionados con las clases desde Visual Basic 6.0 y anteriores
El primer: Usarla en lugar de un array.
Seguramente ocupará más memoria y puede que sea más lento, pero la ventaja es que no es necesario "redimensionar" el array cada vez que se añade o quita un elemento.
Realmente no es necesario usar clases para este menester, sólo con una colección sería suficiente, veámoslo:¿Quién no ha necesitado procesar datos de forma "secuencial" e ir incrementando las coincidencias de determinados valores? (Candemore... hasta parece difícil de explicar esto...8-) )
Pongamos un ejemplo trivial y casi inútil: Imaginaros que queremos comprobar cuantos archivos de tipos diferentes hay en un directorio, es decir que si hay 5 de tipo BAS, 10 de tipo FRM, 8 de tipo FRX, etc, nos lo muestre.El procedimiento a seguir sería:
1- Leer cada archivo del directorio
2- Comprobar si el tipo procesado ya existe
3- Si existe, incrementar la cantidad de este tipo
4- Si no existe, guardar este nuevo tipo
5- Repetir hasta que no queden más archivos.Usando el Basic de toda la vida, con una variable definida para el nombre y la cantidad, sería:
Type tArchivo Extension As String Cantidad As Integer End Type Dim Archivos() As tArchivo Dim a$, b$ Dim i%, j%, k%, Hallado% 'Leer cada archivo del directorio a$ = Dir$("*.*") i% = 0 Do While Len(a$) 'Comprobar la extensión k% = Instr(a$,".") b$="" If k% Then b$ = Mid$(a$,k%+1) 'Comprobar si ya está en la "lista" Hallado% = False For j%=1 to i% If Archivos(j%).Extension = b$ Then 'Si está incrementar la cantidad de veces Archivos(j%).Cantidad = Archivos(j%).Cantidad + 1 'Flag para saber que lo hemos hallado Hallado% = True 'No comprobar más, así que salimos del For Exit For End If Next 'Si no está en la "lista" añadirlo If Not Hallado% Then i% = i% + 1 'Re-dimensionar la variable sin perder los datos anteriores Redim Preserve Archivos(i%) as tArchivo Archivos(i%).Extension = b$ Archivos(i%).Cantidad = 1 End If a$=Dir$ Loop 'Mostrar los datos Print "Extensión","Cantidad" For j%=1 to i% Print Archivos(j%).Extension, Archivos(j%).Cantidad NextBueno este sería el ejemplo "clásico", ahora veamoslo usando una colección.
Definiremos una clase equivalente a la variable tArchivo
'Crear un módulo de Clase (tipo cls) con el Nombre cArchivo 'Añadir estas propiedades: Public Extension As String Public Cantidad As Integer 'Esto ponerlo en el módulo de prueba (en el Sub Main si es un módulo BAS) 'Colección para guardar elementos de la clase Archivo Dim Archivos as New Collection 'Variable temporal de la clase Archivo Dim tArchivo as New cArchivo Dim a$, b$ Dim k% 'La rutina de error hará la parte "sucia" del trabajo On Local Error Resume Next 'Leer cada archivo del directorio a$ = Dir$("*.*") Do While Len(a$) 'Comprobar la extensión k% = Instr(a$,".") b$="" If k% Then b$ = Mid$(a$,k%+1) 'Comprobar si ya está en la "lista" Set tArchivo = Archivos(b$) 'Esto es lo mismo que: Set tArchivo = Archivos.Item(b$) If Err Then 'No existe, añadirlo Err = 0 Set tArchivo = Nothing tArchivo.Extension = b$ tArchivo.Cantidad = 1 Else 'Ya existe, incrementar la cantidad tArchivo.Cantidad = tArchivo.Cantidad + 1 End If 'Añadirlo a la colección Archivos.Add tArchivo, tArchivo.Extension If Err Then 'Ya existía, quitarlo y volverlo a añadir Archivos.Remove tArchivo.Extension Archivos.Add tArchivo, tArchivo.Extension Err = 0 End If a$=Dir$ Loop 'Mostrar los datos Print "Extensión","Cantidad" For Each tArchivo In Archivos Print tArchivo.Extension, tArchivo.Cantidad NextEl ejemplo usando clases, está en el archivo: cls_ej01.zip (+/- 1.941 bytes)
Bueno ya está, usando la clase y la colección.
He usado el error que da al añadir un elemento a una colección cuando ya existe, (no pueden haber dos elementos en una misma colección con la misma clave), para comprobar que ya existía. Lo mismo ocurre cuando se quiere "tomar" un elemento de una colección y no existe: da error.Por supuesto se podría haber creado un "método" en la colección para añadir los datos, en lugar de hacerlo en el código normal. (Siempre que veo "aclaraciones" como esta en los libros, me digo ¿y por qué no lo explicas?)
Así que pasemos a la acción y veámoslo en la práctica:
Ahora como en las series por capítulos de la tele:
La respuesta EL AÑO QUE VIENE, permanezcan atentos a esta pantalla.No es "coña" es que son más de las 6 y mañana/hoy hay que seguir currando, 8-]
Ah!, Feliz Año nuevo a todos.
Bueno, ya estoy por aquí de nuevo... ¿Que tal las uvas? Espero que fueran de la buena suerte.
Lo prometido es deuda, os explico un poco y después pongo los listados.
Para este menester, he creado una clase nueva, en la cual se guarda una colección de la clase cArchivo, en lugar de usar la colección directamente, esta clase/colección tiene una función: Archivos, con un parámetro opcional que será, si se especifica, el ITEM que queremos obtener y si no se especifica, devuelve la colección, (fijaros que el tipo devuelto por la función es Variant y este tipo se lo "traga" todo).
Al especificar el parámetro, la función comprueba si ya existe, si es así devuelve ese item. Si no existe, lo añade a la colección. Pero en cualquier caso devuelve bien el nuevo dato, bien el dato especificado en el parámetro, de esta forma se puede incrementar el contenido de la Cantidad de la misma forma que se haría con una variable normal.
¿No queda claro?
Veamos el ejemplo:
x.Archivos("cls").Cantidad = x.Archivo("cls").Cantidad + 1
Primero se procesa la parte derecha de la expresión, es decir lo que está después del signo igual:
x.Archivos("cls").Cantidad + 1
x.Archivos("cls") devuelve un objeto de la clase cArchivo cuya Extensión es "cls", la primera vez que esto ocurra, lo creará, por tanto objeto.Cantidad será 0 (cero), se le incrementa 1 (+ 1) y se almacenará en el objeto de la colección cuya Extensión sea "cls" (parte izquierda de la expresión)
Si se hace de nuevo este proceso el valor devuelto por objeto.Cantidad será 1, así que al incrementarlo, se convertirá en 2, etc.
¿Más claro ahora?
Espero que sí. De todos modos si hay algo que no entendáis, no dudéis en preguntar. Aunque algunas veces es suficiente con saber que funciona, sin necesidad de entrar en más detalles... 8-)
En fin vamos con los listados del ejemplo:La clase cArchivo es la misma que en el ejemplo anterior:
'Módulo de Clase (tipo cls) con el Nombre cArchivo 'Propiedades: Public Extension As String Public Cantidad As Integer 'Módulo de Clase con el Nombre cArchivos Option Explicit 'Colección de la clase cArchivo Private colArchivos As New Collection Public Function Archivos(Optional Index As Variant) As Variant 'Si se especifica el Index, se devuelve ese item 'sino se devuelve la colección Static tArchivo As New cArchivo On Local Error Resume Next 'Si no se especifica el parámetro... If IsMissing(Index) Then Set Archivos = colArchivos 'Devolver la colección Else 'Devolver el item indicado (si existe) Set Archivos = colArchivos.Item(Index) If Err Then 'No existe, así que añadirlo Err = 0 Set tArchivo = Nothing 'Necesario para dejar "vacío" el objeto tArchivo.Extension = Index 'Añadirlo a la colección colArchivos.Add tArchivo, tArchivo.Extension 'La función devuelve una "copia" del objeto Set Archivos = tArchivo End If End If 'Liberar memoria Set tArchivo = Nothing End Function 'Esta es la prueba... 'Colección para guardar elementos de la clase Archivo Dim Lista As New cArchivos 'Variable temporal de la clase Archivo Dim tArchivo As New cArchivo Dim a$, b$ Dim k% 'Leer cada archivo del directorio a$ = Dir$("*.*") Do While Len(a$) 'Comprobar la extensión k% = InStr(a$, ".") b$ = "" If k% Then b$ = Mid$(a$, k% + 1) 'Esto es todo lo que hay que hacer, 'del resto se encarga la función Archivos Lista.Archivos(b$).Cantidad = Lista.Archivos(b$).Cantidad + 1 a$ = Dir$ Loop 'Mostrar los datos Print "Extensión", "Cantidad" For Each tArchivo In Lista.Archivos Print tArchivo.Extension, tArchivo.Cantidad NextRealmente es más "corta" que el ejemplo anterior, ya que el trabajo lo realiza la función Archivos y aquí es donde entra el consejo de los que defienden las clases: Podemos cambiar el funcionamiento interno de la función Archivos sin que ello nos obligue a cambiar la forma de usarla, es decir el código:
Lista.Archivos(b$).Cantidad = Lista.Archivos(b$).Cantidad + 1
permanecerá, (o así "debería" ser), igual; independientemente de cómo "actúe" la función internamente.
BUF! Creo que ya está bien para el primer día del año.El segundo ejemplo usando clases, está en el archivo: cls_ej02.zip (+/- 2.380 bytes)
3.- Crear una libreria In-Process OLE (toma ya!)
Eso de In-Process OLE, queda muy bien, pero ¿qué es?
Pues una DLL, es decir una librería dinámica a la que podemos llamar desde nuestro programa, pero en lugar de hacerlo como es habitual, lo que se hace es usar los objetos que expone. ¿?
Si no te has enterado, no importa, ya verás como te quedas con la copla.
He incluido un ejemplo para ver esto en funcionamiento.
El programa, de ejemplo, es bastante simple:
Muestra unos nombres en un combo y espera que se escriba algo en un text box. Una vez pulsado Aceptar o Cancelar, devuelve a la aplicación que la ha llamado el nombre seleccionado del combo y lo que se haya escrito en el text-box.
En esta librería se incluyen dos clases: cUser y cClave, además de un form para mostrar al usuario.
En este tipo de librerías, se deben incluir forms y mostrarlos modalmente, es decir que hasta que no se cierre (o se oculte), el programa no debe seguir. Tiene su lógica, porque normalmente se usa para pedir datos, etc.
Para usar componentes OLE, que no sean "Modales", se debe hacer con la otra forma: Out-Process, en estos, si hay forms, no deben ser modales... Ya lo verás en un próximo ejemplo, que intentaré que esté lo antes posible.La clase cUser es muy simple: sólo tiene dos propiedades, que se declaran públicas para que se puedan usar externamente. También hay que indicarle, por medio de las propiedades, que es multiuso y pública.
VERSION 1.0 CLASS BEGIN MultiUse = -1 'True END Attribute VB_Name = "cUser" Attribute VB_Creatable = True Attribute VB_Exposed = True '------------------------------ 'Clase para Usuario (20/Ene/97) '©Guillermo Som, 1996-97 '------------------------------ Option Explicit ' Public Nombre As String Public Clave As StringLa clase cClave ya es un poco más larguilla... Las propiedades también son Multiuso y Pública. Sólo tiene un método: la función Acceso. Esta función es la que se usará para asignar los datos y mostrar el form...
'-------------------------------------------------------- 'Entrada a la función de pedir las claves de acceso 'Usuarios Array (colección) de tipo cUser (sólo se usa el Nombre) 'Modo 1, seleccionar usuario y NO pedir clave ' 2, NO seleccionar usuario y pedir clave ' 3, seleccionar usuario y pedir clave 'Usuario El mostrado inicialmente 'msgClave Para el caption del form ' 'Devuelve el usuario seleccionado y la clave introducida ' o vacio si se pulsa Cancelar '--------------------------------------------------------- Public Function Acceso(ByVal Usuarios As Variant, ByVal Modo As Integer, _ Optional ByVal Usuario As Variant, Optional ByVal msgClave As Variant) As cUser Dim frmClaves As New fPedirClave 'Se declara el form Dim tUsuario As New cUser 'Copia temporal de la clase cUser Dim i As Integer Dim j As Integer Dim vTmp As String Dim sUser As String 'Caption a mostrar If IsMissing(msgClave) Then vTmp = "Clave de Acceso" Else vTmp = msgClave End If 'Primer usuario a mostrar If IsMissing(Usuario) Then sUser = Usuarios(1).Nombre Else sUser = Usuario End If With frmClaves .Caption = vTmp .TxtClave = "NINGUNA" .Combo1.Clear j = 0 i = 0 'Añadir los nombres al Combo y averiguar en que posición está. For Each tUsuario In Usuarios .Combo1.AddItem tUsuario.Nombre j = j + 1 If sUser = tUsuario.Nombre Then i = j - 1 End If Next If i = -1 Then i = 0 End If .Combo1.ListIndex = i ' If Modo = 1 Then .TxtClave.Enabled = False ElseIf Modo = 2 Then .Combo1.Enabled = False End If 'El form hay que mostrarlo en modo Modal .Show vbModal Set tUsuario = Nothing If .Cancelado Then tUsuario.Nombre = "" tUsuario.Clave = "" Else tUsuario.Nombre = .Combo1.Text tUsuario.Clave = .TxtClave End If Set Acceso = tUsuario End With 'Liberar la memoria asignada... Set tUsuario = Nothing Unload frmClaves End FunctionEl form, además del combo, el text-box y los botones de Aceptar y Cancelar, tiene una propiedad pública: Cancelar, que se usa para comprobar si se ha pulsado en cancelar o se ha cerrado la ventana de otra forma distinta a pulsar en los botones.
El código del form, es bastante simple..., tampoco necesita ser mas sofisticado... 8-)'-------------------------------------------------- 'Form para pedir las claves de acceso (31/May/96) '©Guillermo Som, 1996-97 ' 'Nueva versión (más simple) (20/Ene/97) '-------------------------------------------------- Option Explicit Private pCancelar As Boolean Private Sub CmdAceptar_Click() pCancelar = False Hide End Sub Private Sub CmdCancelar_Click() pCancelar = True Hide End Sub Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer) 'Si se cierra de cualquier forma, salvo por medio del código... 'actuará igual que si se hubiese pulsado en cancelar If UnloadMode <> vbFormCode Then pCancelar = True End If End Sub Private Sub Form_Unload(Cancel As Integer) 'Liberar la memoria Set fPedirClave = Nothing End Sub Private Sub TxtClave_GotFocus() 'Seleccionar todo el texto TxtClave.SelStart = 0 TxtClave.SelLength = Len(TxtClave) End Sub Public Property Get Cancelado() As Boolean Cancelado = pCancelar End PropertyAdemás de las dos clases y el form, para crear una DLL-OLE, hay que entrar por un Sub Main, pero no es necesario que haga nada, el código es el siguiente: (yo lo uso para todas las clases que hago)
'-------------------------------------------------- 'OLEMain.bas (11/Jun/96) '©Guillermo Som, 1996-97 ' 'Módulo genérico para Librerías OLE '-------------------------------------------------- Option Explicit Sub Main() ' 'Sub Main es necesario para in-process OLE server ' End SubPor último decir que debes indicarle a VB que es una librería DLL, para ello, especifica lo siguiente:
Selecciona Tools/Options...
En la solapa Project, selecciona Ole Server y en Application Description escribe lo que quieras que muestre cuando hagas referencia a esta librería.
En la solapa Advanced, selecciona Break in Class Module y Use OLE DLL RestrictionsBueno, eso es todo. Para probarlo en el entorno, primero cargas este proyecto en VB. Lo ejecutas, parecerá que no hace nada. Pero si que está haciendo, está exponiendo las dos clases.
Abre otra copia de VB y en el menú Tools/References... habrá una referencia a este proceso. Si pulsas en el Object Browser, verás las dos clases y los objetos que puedes usar.
Para los listados completos y un ejemplo de un programa de mensajería interna:
Baja el fichero: PedirCla.zip (3.777 bytes)
Ejemplo que usa estas clases: Mensajes.zip (29.112 bytes)Nota:
La versión VB en castellano, indicará estas opciones de otra forma, pero no sé cual será la traducción.
Lo siento, pero no me he actualizado a esa versión porque cuando la probé, me dió errores "tontos", como el de traducir True y False por Verdadero y Falso. Al usar el programa compilado, no funcionaba al no "entender" estos valores en Castellano. No sé si lo han corregido, pero tampoco lo voy a comprobar.
4.- Un poco más de clase (16/Feb)
Baja el listado con los ejemplos (rdir.zip 5.5 KB)
Este ejemplo que voy a poner es para leer todos los archivos de un directorio y de todos los directorios que penden de él.
Realmente no son todos los archivos, sino los de la extensión especificada.
El concepto del uso de las clases es básicamente el mismo que en el primer ejemplo, pero con algunas cosillas nuevas.
He incluido un form de prueba, que no voy a listar aquí, si quieres ver el programa completo, bájate el listado de ejemplo.
El corazón de este tinglado se basa en la función RecorrerDir, que es recursiva, es decir se llama así misma, para poder analizar los directorios que están por debajo del que se analiza.
Las clases se usan para almacenar los archivos encontrados.
La primera es básica y sólo tiene dos propiedades el ID o clave del elemento y Nombre que usaremos para guardar el nombre del archivo y el path.
La segunda maneja una colección de la clase básica y tiene un método, Nuevo, para añadir nuevos elementos a la colección
Veamos los listados de estas clases:
La primera es "suficientemente" simple:'-------------------------------------------------- 'cNombre (15/Feb/97) 'Clase de uso general, para guardar un nombre ' '©Guillermo Som Cerezo, 1997 '-------------------------------------------------- Option Explicit ' 'Esta propiedad se usará para la clave del elemento Public ID As String 'Este otro para guardar el nombre del archivo Public Nombre As StringLa segunda clase cNombres:
Tiene una colección privada a la que se accede mediante el método Nombres.
Y un método: Nuevo, para añadir nuevos elementos a la colección.'-------------------------------------------------- 'cNombres (15/Feb/97) 'Clase de uso general, 'Esta es una colección de objetos cNombre ' '©Guillermo Som Cerezo, 1997 '-------------------------------------------------- Option Explicit Private colNombres As New Collection Public Function Nombres(Optional Index As Variant) As Variant 'El acceso a esta función permitirá usar 'los datos de la clase cNombre 'Si se especifica el Index, se devuelve ese item 'sino se devuelve la colección ' Static tNombre As New cNombre On Local Error Resume Next 'Si no se indica el index, se devuelve la colección If IsMissing(Index) Then Set Nombres = colNombres Else 'Comprobar si está en la colección Set Nombres = colNombres.Item(Index) 'Si produce error, es que no existe If Err Then Err = 0 Set tNombre = Nothing tNombre.ID = Index 'Añadirlo colNombres.Add tNombre, tNombre.ID 'Devolver el item creado Set Nombres = tNombre End If End If 'Liberar memoria Set tNombre = Nothing End Function Public Sub Nuevo(sNombre As String) 'Añade una nueva entrada a la colección Static NumEntradas As Integer Dim sID As String 'Incrementamos el número de entradas NumEntradas = NumEntradas + 1 'Asignamos la clave del elemento sID = "nn" & Format(NumEntradas, "0000") 'Usamos la función Nombres de esta clase Me.Nombres(sID).Nombre = sNombre End SubAhora veamos la función que analiza los directorios y asigna los elementos de la colección:
Public Function RecorrerDir(ByVal NewPath As String, PathAnt As String, col As Variant) As Boolean 'Función recursiva para recorrer los directorios 'basada en un ejemplo de Visual Basic para MS-DOS ' Dim NumDirs As Integer Dim OldPath As String Dim sFic As String Dim ThePath As String Dim res As Boolean Dim i As Integer Dim sID As String On Local Error GoTo RutinaError NumDirs = Dir1.ListCount Do While NumDirs > 0 DoEvents If Cancelar Then RecorrerDir = True Exit Function End If OldPath = NewPath If Dir1.ListCount > 0 Then Dir1.Path = Dir1.List(NumDirs - 1) 'para crear la entrada de este directorio sID = Dir1.Path res = RecorrerDir((Dir1.Path), OldPath, col) End If If res Then RecorrerDir = True Exit Function End If NumDirs = NumDirs - 1 Loop 'Asignar la extensión que queremos mostrar File1.Pattern = Ext If File1.ListCount Then If Len(NewPath) <= 3 Then ThePath = NewPath Else ThePath = NewPath & "\" End If For i = 0 To File1.ListCount - 1 DoEvents If Cancelar Then RecorrerDir = True Exit Function End If sFic = ThePath & File1.List(i) 'Añadir a la colección col.Nuevo sFic Next End If If Len(PathAnt) Then Dir1.Path = PathAnt End If RecorrerDir = False Exit Function RutinaError: If Err = 7 Then MsgBox "No hay suficiente memoria para completar la tarea", vbCritical, "RecorrerDir" Else MsgBox "ERROR: " & CStr(Err) & ", " & Error$, vbCritical, "RecorrerDir" End If RecorrerDir = True End FunctionBueno, estos son los listados. El resto del formulario, tiene los botones y los text-box para la entrada de datos, etc.
Lo que hay de novedad es el método Nuevo de la clase cNombres.
Es muy simple su funcionamiento, con la variable estática NumEntradas, lleva la cuenta de los elementos asignados a la colección, asigna el valor para la clave y llama a la función Nombres para añadir el nuevo elemento.
Veamos por último la parte del código que se encarga de llamar a la función RecorrerDir, leer los elementos de la colección y añadirlos a un listbox:t1 = Timer If RecorrerDir(Dir1.Path, "", colDir) = False Then t3 = Timer - t1 'Mostrar los datos List2.Clear For Each tNombre In colDir.Nombres DoEvents If Cancelar Then Exit For List2.AddItem tNombre.Nombre Next t2 = Timer - t1 Label3 = colDir.Nombres.Count & " archivos, procesados en: " & Format(t3, ".00") & " seg, listados en: " & Format(t2, ".00") & " seg" Label3.Visible = True End IfComo puedes ver, usando las clases se simplifican las cosas. Aunque para decir la verdad, podríamos haber usado el ListBox directamente en la función recursiva y hubiesemos obtenido el mismo resultado, pero mucho más lento!!!
En las pruebas que he realizado, asignar 365 archivos de 24 directorios, tardó en procesarlo 6.64 segundos y en asignarlo al ListBox 21.91.
5.- Y más todavía, con y sin librería OLE (11/Mar)
Revisión del 8 de Abril: Si quieres ver los listados de la nueva revisión, pásate por este link.
En él encontrarás la explicación y los listados, tanto de la librería OLE como la forma de usarlo sin librería.¡LOS HE QUITADO DE ESTA PÁGINA, PORQUE LOS DE AQUÍ YA ESTABAN OBSOLETOS!
MUY IMPORTANTE: Los listados y las imágenes están en la utilidad SelDir
Es que las mentes "calenturientas" nunca paran! Y además, me gusta complicarme la vida.
Lo que viene a continuación es una revisión del caso anterior, pero mejorado y más funcional.En líneas generales lo que tenemos aquí es lo siguiente:
Una librería OLE que permite seleccionar un directorio de una caja de diálogo. Sólo el directorio.
Y además permite que se procesen todos los archivos de una determinada extensión que estén en ese directorio.
Y para "liar" más la cosa, también hay una función/método que puede leer todos los archivos de la extensión especificada y los que estén en todos los directorios que haya por "debajo" del indicado.
Por supuesto con ejemplos: dos ejemplos. El primero usando la librería (se incluye sólo el listado de la librería, para usarla como componente OLE, deberás compilarla). El segundo usando las clases en el propio proyecto.
Incluyo por tanto dos archivos VBP cada uno con una definición distinta de la constante para compilación condicional.Veamos primero los archivos de prueba. Realmente es un archivo, pero que se puede cargar como programa independiente, es decir, no necesitando ningún objeto OLE o bien usando la librería creada con: OLE_SelDir.vbp
Para el primer ejemplo deberás usar el proyecto: test_SelectDir.vbp
Para el segundo, una vez instalada la DLL o bien ejecutandose en otra instancia de VB4, usa: test_oSelDir.vbp
¿Te lias? No importa, vamos a ver las cosas y saldrás de dudas.
Veamos un gráfico con el form de prueba y ahora veremos los procedimientos y las explicaciones:(!!!)
Fijate en la declaración de las clases/objetos para manejar la clase/objeto/librería OLE.
Si usamos el primer proyecto, (test_SelectDir.vbp), entonces estará definida la constante esOLE como esOLE = 0
Pero si el proyecto cargado es: test_oSelectDir.vbp, estará definida como esOLE = -1
Con la compilación condicional, podemos usar un mismo módulo, para varias cosas distintas, en este ejemplo para usar o no unos objetos de una librería OLE.Bien, ahora veamos los componentes de la librería OLE. Es decir el "tinglado" este para Seleccionar los Directorios.
Si quieres usarlo como librería OLE, deberás usar el proyecto OLE_SelDir.vbp. Está compuesto por los siguientes archivos:cNombre.Cls La clase básica, ya la vimos antes, en el ejemplo anterior. cNombresA.cls Una colección de la clase cNombre.Cls, igual que en el ejemplo anterior, sólo cambia el nombre, ¡creo! cSelectDir.Cls Esta clase es la encargada de procesar los directorios y archivos SelectDir.Frm El form que muestra los directorios a seleccionar y el que hace el trabajo duro En él está la función RecorrerDir que es "casi" igual que el del ejemplo anterior OLEMain.bas El módulo que uso siempre para crear las librerías OLE(!!!)
Resumiendo, si quieres usar la clase desde una librería OLE, debes declarar las variables de la siguiente forma:
'Si usamos la librería OLE Dim tNombre As New oSelDir.cNombre Dim cSelDir As New oSelDir.SelDirPara usar las clases junto on el programa que las vaya a utilizar, declara las variables así:
'Si usamos las clases cargadas Dim tNombre As New cNombre Dim cSelDir As New SelDirPara "procesar" todos los archivos de una Extensión y en todos los directorios que estén por debajo del indicado, úsalo de esta forma:
Set colDir = cSelDir.Directorios(sRuta, sExtension)Si quieres procesar sólo los directorios, no indiques la extensión:
Set colDir = cSelDir.Directorios(sRuta)O bien, hazlo con una cadena vacía:
Set colDir = cSelDir.Directorios(sRuta, "")Y si la intención es la de procesar sólo un directorio, pues:
'Los archivos del directorio especificado Set colDir = cSelDir.Directorio(sRuta, sExtension)
Espero que puedas sacarle rendimiento a todo esto.
Si aún tienes dudas de cómo crear librerías de objetos OLE y de cómo exponer las clases/objetos incluidas en la librería...
Pregúntame, pero antes te recomiendo que le eches un vistazo a los listados, que para eso los incluyo.
De todas formas me gustaría que me comentaras algo sobre todo esto. Entre otras cosas, me servirá para saber que no me estoy "hinchando" de escribir y hacer pruebas para "nada". Tu mismo!
Baja el listado con los ejemplos (seldir.zip 10.8 KB)
NOTA: Estos listados son los anteriores, para ver la nueva versión, pasate por este link.
10.- Más artículos sobre los objetos: publicados originalmente en VB Online edición USA. (14/Ago/98)
Pues eso, estos dos artículos me los publicaron en la edición norte americana de VB Online, en los meses de Mayo y Julio de este mismo año.
Pero no te preocupes, que no están en inglés; estos son los originales que le envié a mi colega Joe LeVasseur para que me los tradujera, aprovecho la ocasión para agradecerle públicamente las molestias que le haya podido producir el hacer de traductor.
¡Gracias Joe!Aquí tienes los links a los dos artículos mencionados: