** NORMAS DEL FORO **
Inicio del foro Inicio del foro > Otros de Microsoft: Windows y Office > Visual Basic Clásico (VB3...VB6)
  Mensajes nuevos Mensajes nuevos RSS - Función recursiva
  Preguntas frecuentes Preguntas frecuentes  Buscar en el foro   Eventos   Registro Registro  Iniciar sesion Iniciar sesion

Tema cerradoFunción recursiva

 Responder Responder
Autor
Mensaje
Medardo Ver desplegable
Colaborador
Colaborador
Avatar

Unido: 03/Marzo/2005
Localización: Cuba
Estado: Sin conexión
Puntos: 1987
Enlace directo a este mensaje Tema: Función recursiva
    Enviado: 26/Octubre/2015 a las 20:54

Hola

 

Está claro que una función recursiva se llama a sí misma, que retorna el valor a la función y vuelve al punto de llamada. Pero les confieso que no recuerdo haberla utilizado.

 

Tengo un procedimiento que sirve para cargar combos. Hay que llamar al procedimiento (que contiene parámetros) por cada uno de los combos a cargar.

 

Se me ha ocurrido entonces, crear un procedimiento que contenga arrays y a su vez, sea recursiva. El procedimiento ya está hecho, el problema está en cómo lograr que sea recursiva.

 

Les pongo el ejemplo:

 

Antes de hacer la llamada:

 

Dim sControl2(2) As String

Dim sCampos2(2) As String

   

sControl2(0) = "dLabProv"

sControl2(1) = "dLabMcpio"

sControl2(2) = "dLabEspecialidad"

   

sCampos2(0) = "Provincia"

sCampos2(1) = "Municipio"

sCampos2(2) = "Especialidad"

 

La llamada:

CargarCombosMultiples frm_DatosPersonales, sControl2, sCampos2

 

Public Sub CargarCombosMultiples(fForm As Form, sControl() As String, sCampos() As String)

    Dim strTextoActual As String

    Dim strTextoAnterior As String

    Dim strAlmacenar As String

    Dim Descomponer As Variant

    Dim rst As New ADODB.Recordset

    Dim cbo As Object

    Dim i As Integer

   

    If rst.State = adStateOpen Then rst.Close: Err.Clear

    rst.Open "Select " & sCampos(i) & " FROM tabPrincipal", cnn, adOpenDynamic, adLockOptimistic

   

    Do While rst.EOF = False

        strTextActual = rst(sCampos(i))

        If strTextActual <> strTextAnterior Then

            Descomponer = Split(strAlmacenar, "\")

            strAlmacenar = strAlmacenar & "\" & strTextActual

        End If

        strTextAnterior = strTextActual

        rst.MoveNext

    Loop

 

    For Each cbo In fForm

        If TypeOf cbo Is ComboBox Then

            If cbo.Name = sControl(i) Then

                cbo.Clear

                Exit For

            End If

        End If

    Next

   

    Dim iMatriz As Integer     

    Dim iCombo As Integer      

    Dim bolYaEsta As Boolean   

 

    For Each cbo In fForm

        If TypeOf cbo Is ComboBox Then

            If cbo.Name = sControl(i) Then

                For iMatriz = 1 To UBound(Descomponer)

                    bolYaEsta = False

                    'vamos comparando cada elemento de la matriz con los elementos añadidos en el combo

                    'la primera vez no entrará a este ciclo

                    For iCombo = 0 To cbo.ListCount - 1

                        'si el elemento del combo es igual al elemento de la matriz...

                        If cbo.List(iCombo) = Descomponer(iMatriz) Then

                            'declaramos la variable a verdadero para que no vuelva a ser añadido

                            bolYaEsta = True

                            'al encontrar una coincidencia, no es necesario

                            'continuar, por tanto, salimos del ciclo

                            Exit For

                        End If

                    Next iCombo

                    'si no se ha encontrado coincidencia, entonces añadimos

                    If bolYaEsta = False Then cbo.AddItem Descomponer(iMatriz)

                Next iMatriz

                Exit For

            End If

        End If

    Next

   

    i = i + 1

   

End Sub

 

¿Cómo logro que este procedimiento sea recursivo para que continúe el ciclo de los array’s que faltan?


Saludos
Desde La Habana, Cuba
Medardo
Arriba
lbauluz Ver desplegable
Administrador
Administrador
Avatar

Unido: 29/Marzo/2005
Localización: Prisión Brieva
Estado: Sin conexión
Puntos: 3174
Enlace directo a este mensaje Enviado: 27/Octubre/2015 a las 19:48
No lo he podido mirar en detalle pero creo que deberias pasarle ek indice que le indique en que iteracion estas,  algo similar a esto


La llamada:

CargarCombosMultiples frm_DatosPersonales, sControl2, sCampos2, 0

 

Public Sub CargarCombosMultiples(fForm As Form, sControl() As String, sCampos() As String, iteracion as integer)

(...)

Dim i As Integer

   i = iteracion

    If rst.State = adStateOpen Then rst.Close: Err.Clear

    rst.Open "Select " & sCampos(i) & " FROM tabPrincipal", cnn, adOpenDynamic, adLockOptimistic

   

(...)

         Next

         i = i + 1

CargarCombosMultiples frm_DatosPersonales, sControl2, sCampos2, iteracion + 1

End Sub


Un saludo.


Luis

Those are my principles, and if you don't like them... well, I have others. Groucho Marx
Arriba
Medardo Ver desplegable
Colaborador
Colaborador
Avatar

Unido: 03/Marzo/2005
Localización: Cuba
Estado: Sin conexión
Puntos: 1987
Enlace directo a este mensaje Enviado: 27/Octubre/2015 a las 22:19

Hola Luis

Gracias por contestar.

Ya había hecho lo mismo, pero sin la iteración. Pero me sigue marcando el mismo error en sControl2, en:

CargarCombosMultiples frm_DatosPersonales, sControl2, sCampos2, iteracion + 1

El error dice:

“Error de tipo: se esperaba una matriz o un tipo definido por el usuario”


Saludos
Desde La Habana, Cuba
Medardo
Arriba
lbauluz Ver desplegable
Administrador
Administrador
Avatar

Unido: 29/Marzo/2005
Localización: Prisión Brieva
Estado: Sin conexión
Puntos: 3174
Enlace directo a este mensaje Enviado: 28/Octubre/2015 a las 01:30
Prueba a cambiar 
Public Sub CargarCombosMultiples(fForm As Form, sControl() As String, sCampos() As String, iteracion as integer)
por
Public Function CargarCombosMultiples (fForm As Form, sControl() As String, sCampos() As String, iteracion as integer)



Un saludo.


Luis
Those are my principles, and if you don't like them... well, I have others. Groucho Marx
Arriba
Medardo Ver desplegable
Colaborador
Colaborador
Avatar

Unido: 03/Marzo/2005
Localización: Cuba
Estado: Sin conexión
Puntos: 1987
Enlace directo a este mensaje Enviado: 28/Octubre/2015 a las 14:14
Hola Luis
Problema resuelto. Explico:

Indicar la función al final, como me indicaste en el mensaje anterior, ya lo había hecho, pero sin la variable ‘iteracion’ y me saltaba, desde el inicio, el mismo error que señalé anteriormente.
Hice entonces la prueba de quitar la llamada recursiva de la función para ver qué pasaba, y fue cuando vi que entraba a la función, realizaba todas las operaciones con relación al primer elemento de la matriz (provincias) y salía sin completar el llenado del resto de los combos. O sea, solo llenaba el combo relacionado con el primer elemento de la matriz.
Esto, unido al error que saltaba: “… se esperaba una matriz…” me hizo pensar que no le estaba llegando todos los elementos, o sea, toda la matriz, sino, solo el primer elemento. Era obvio entonces que la declaración de las variables relacionadas con la matriz tenía que ser pública. Eso fue lo que hice y ya el error no saltaba, pero sin la variable ‘iteracion’ y ahí se formaba un ciclo sin salida, solo con el primer elemento de la matriz.
De modo que, declarar las variables públicas para que lleguen todos los elementos de la matriz e incorporar la variable ‘iteracion’ para indicar en qué índice de la matriz se encuentra, es la solución final.

Expongo el código final:

En un módulo, declaramos las variables públicas:
Public sControl2(2) As String
Public sCampos2(2) As String

En el formulario desde donde se va a realizar la llamada:

sControl2(0) = "dLabProv"
sControl2(1) = "dLabMcpio"
sControl2(2) = "dLabEspecialidad"
    
sCampos2(0) = "Provincia"
sCampos2(1) = "Municipio"
sCampos2(2) = "Especialidad"

La llamada:
CargarCombosMultiples frm_DatosPersonales, sControl2, sCampos2, 0

Public Sub CargarCombosMultiples(fForm As Form, sControl() As String, sCampos() As String, iteracion As Integer)
    Dim strTextoActual As String
    Dim strTextoAnterior As String
    Dim strAlmacenar As String
    Dim Descomponer As Variant
    Dim rst As New ADODB.Recordset
    Dim cbo As Object
    Dim i As Integer
    
    i = iteracion
    If iteracion - 1 = UBound(sCampos) Then Exit Sub

    If rst.State = adStateOpen Then rst.Close: Err.Clear
    rst.Open "Select " & sCampos(i) & " FROM tabPrincipal", cnn, adOpenDynamic, adLockOptimistic
    
    Do While rst.EOF = False
        strTextActual = rst(sCampos(i))
        If strTextActual <> strTextAnterior Then
            Descomponer = Split(strAlmacenar, "\")
            strAlmacenar = strAlmacenar & "\" & strTextActual
        End If
        strTextAnterior = strTextActual
        rst.MoveNext
    Loop

    For Each cbo In fForm
        If TypeOf cbo Is ComboBox Then
            If cbo.Name = sControl(i) Then
                cbo.Clear
                Exit For
            End If
        End If
    Next
    
    Dim iMatriz As Integer      
    Dim iCombo As Integer       
    Dim bolYaEsta As Boolean    

    For Each cbo In fForm
        If TypeOf cbo Is ComboBox Then
            If cbo.Name = sControl(i) Then
                For iMatriz = 1 To UBound(Descomponer)
                    bolYaEsta = False
                    'vamos comparando cada elemento de la matriz con los elementos añadidos en el combo
                    'la primera vez no entrará a este ciclo
                    For iCombo = 0 To cbo.ListCount - 1
                        'si el elemento del combo es igual al elemento de la matriz...
                        If cbo.List(iCombo) = Descomponer(iMatriz) Then
                            'declaramos la variable a verdadero para que no vuelva a ser añadido
                            bolYaEsta = True
                            'al encontrar una coincidencia, no es necesario
                            'continuar, por tanto, salimos del ciclo
                            Exit For
                        End If
                    Next iCombo
                    'si no se ha encontrado coincidencia, entonces añadimos
                    If bolYaEsta = False Then cbo.AddItem Descomponer(iMatriz)
                Next iMatriz
                Exit For
            End If
        End If
    Next
    
    i = i + 1
    CargarCombosMultiples frm_DatosPersonales, sControl2, sCampos2, iteracion + 1
End Sub

En el código se hace referencia solo a la tabla ‘tabPrincipal’, quiere decir que, los datos cargados en los combos pertenecen a una misma tabla. Sin embargo, con este método se pueden cargar combos con datos de distintas tablas. Solo sería crear otra matriz con el nombre de las tablas:

Declaramos pública la matriz:
Public sTabla2(2) As String

Indicamos los elementos de la matriz:
sTabla2(0) = "lstProvincia"
sTabla2(1) = "lstSindicato"
sTabla2(2) = "lstEspecialidad"

En la llamada a la función, agregamos la matriz de las tablas:
CargarCombosMultiples frm_DatosPersonales, sControl2, sCampos2, sTabla2, 0

En la declaración de la función, agregamos una matriz más:
Public Sub CargarCombosMultiples(fForm As Form, sControl() As String, sCampos() As String, sTabla() As String, iteracion As Integer)

Dentro de la función, al abrir el recordset, indicamos la matriz de las tablas
rst.Open "Select " & sCampos(i) & " FROM " & sTabla(i) & "", cnn, adOpenDynamic, adLockOptimistic

Y al final de la función, en su llamada recursiva, agregamos la matriz:
CargarCombosMultiples frm_DatosPersonales, sControl2, sCampos2, sTabla2, iteracion + 1

De esta forma, se pueden cargar varios combos, con datos de una o varias tablas, realizando una sola llamada a un procedimiento. Pero, como mismo se trata ahora de carga de combos, se puede tratar de cualquier otra operación.

Sin duda alguna, no es lo mismo realizar varias llamadas a una función o procedimiento, que una sola llamada para realizar las mismas operaciones. Se gana en rendimiento.

Saludos
Desde La Habana, Cuba
Medardo
Arriba
 Responder Responder
  Compartir tema   

Ir al foro Permisos de foro Ver desplegable