** 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 - Acelerar la carga de un combo
  Preguntas frecuentes Preguntas frecuentes  Buscar en el foro   Eventos   Registro Registro  Iniciar sesion Iniciar sesion

Tema cerradoAcelerar la carga de un combo

 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: Acelerar la carga de un combo
    Enviado: 20/Octubre/2015 a las 15:15
Hola

Mi pregunta es sencilla:

¿Es posible cargar un ComboBox sin necesidad de recorrer una tabla?

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: 20/Octubre/2015 a las 16:13
Hola Medardo.

Puedes cargarlo directamente de un array.

Option Explicit

Private Sub UserForm_Initialize()
    Dim n As Long
    Dim FArray(100)
    
    For n = 1 To 100
        FArray(n) = "Numero: " & n
    Next n
    
    ComboBox1.ListRows = n + 1
    ComboBox1.List() = FArray
End Sub

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: 20/Octubre/2015 a las 19:26

Gracias Ibauluz por contestar.

Ok, estoy de acuerdo. Pero voy a ser más explícito.

Yo necesito el listado del primer apellido de todos los clientes que se encuentran en una tabla (tabPrincipal) y cargarlos en un combo, PERO, sin recorrer la tabla que tiene cerca de 1000 (mil) registros.

No es el único combo que se carga en ese formulario, por eso la demora, que está en el recorrido (a la misma tabla), por cada combo (en busca de diferentes datos). He ahí la causa de mi pregunta. En programación .Net se puede hacer, lo vi investigando por Internet, pero no lo he visto en VB6.

No sé si me pude explicar mejor o no logré entenderte.
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: 20/Octubre/2015 a las 19:54
Hola Medardo

Entiendo que lo que realmente necesitas es leer de golpe los 1.000 registros en un array y presentar ese array en el combo, creo que algo similar a esto deber'ia funcionar (lo siento, no lo puedo probar aqu'i)


Private Sub UserForm_Initialize()

    Dim dbs As DAO.Database
    Dim rst As DAO.Recordset
    Dim FArray As Variant
    Set dbs = CurrentDb
    Set rst = dbs.OpenRecordset("SELECT apellido1 FROM tabPrincipal", dbOpenSnapshot)

    rst.MoveLast
    rst.MoveFirst
    FArray = rst.GetRows(rst.RecordCount) ' Cargar recordset en array

    rst.Close: Set rst = Nothing
    dbs.Close: Set dbs = Nothing
    ComboBox1.ListRows = UBound(FArray) + 1
    ComboBox1.List() = FArray
End Sub
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: 20/Octubre/2015 a las 20:36
Ibauluz
La propiedad ListRows no aparece en el combo.
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: 20/Octubre/2015 a las 22:22
Yo lo he probado en Excel, no se si exista en VB 6, indica al combo cuantas filas visibles tiene en total.

No es importante para esta prueba, si no recuerdo mal, en VB el numero por defecto de filas que se muestran era al rededor de 10 o 12.

Prueba a comentar esa linea.

(Sin acentos por usar teclado en Ingles).

Un saludo.

Luis


Editado por lbauluz - 20/Octubre/2015 a las 22:23
Those are my principles, and if you don't like them... well, I have others. Groucho Marx
Arriba
mounir Ver desplegable
Colaborador
Colaborador


Unido: 09/Febrero/2009
Localización: Asturias-España
Estado: Sin conexión
Puntos: 4761
Enlace directo a este mensaje Enviado: 20/Octubre/2015 a las 23:08
Hola!

Debes de añadir a tu proyecto el componente "Microsoft Form 2.0 Object Library" ahí tienes un ComboBox con la propiedad ListRows para mostrar el número de elementos que quieras.
Un Saludo.
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: 21/Octubre/2015 a las 17:10

Hola Luis y Mounir

Muchas gracias por contestar.

Como dice Mounir, en ese componente aparece un combo con la propiedad ListRows, por lo que probé el código de Luis, pero solo me muestra el primer elemento.

He estado horas revisando en Internet y no he encontrado un ejemplo concreto que resuelva el problema en VB6.

Se me ha ocurrido algo que aún estoy por probar. Por ejemplo, tener en memoria una variable (array) con los elementos capturados hasta el momento de conformar el array, que puede ser al iniciar el programa (creo que es el momento más lógico), y luego, al cargar los combos (que es en un formulario de búsqueda), comparar la cantidad de registros (elementos) cargados en memoria con la cantidad de registros en el momento de cargar el formulario de búsqueda, y solo agregar a partir de que existan diferencias entre la cantidad de registros (si existiera tal diferencia). De esa manera, la carga sería mínima y por supuesto, el tiempo mucho más rápido.

Si alguien tiene alguna otra sugerencia, se lo agradecería muchísimo.
Saludos
Desde La Habana, Cuba
Medardo
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: 22/Octubre/2015 a las 21:10
Hola

Bueno, resolví el problema. Les cuento con detalles:

Primero, hace tiempo me hice un procedimiento para cargar combos sin repetir los elementos, por ejemplo, en caso de apellidos o nombres. Pero al hacer la llamada a ese procedimiento, abre un recordset y realiza un ciclo a una tabla, según se indica en los parámetros. Eso puede ser aceptable cuando se trata de cargar datos de diferentes tablas, pero en mi caso no es así, todos los combos (cinco) se cargan con datos de la misma tabla, por tanto, no era necesario realizar la llamada al procedimiento por cada combo, sino, en una sola llamada con un solo ciclo a la tabla. Eso fue lo primero que cambié.

Segundo, para llegar al formulario que carga dichos combos, primero hay que abrir el formulario de captura, y como ya había dicho anteriormente, en vez de abrir el recordset en el momento de cargar los combos, aproveché la carga del formulario de la captura y creé matrices según la cantidad de combos, con los elementos que necesitaba cada combo, quedando en memoria mientras permanecía abierto el formulario de captura. Una vez que cargaba el formulario de los combos, los cargaba con los elementos de las matrices.

La operación de acceso a los elementos de una matriz es mucho más rápida que cualquier otra estructura porque utilizan menos memoria. El llenado de y desde una matriz es mucho más rápido que de un objeto Recordset.

Con todo esto, les puedo decir que, con 1586 registros, la carga de los combos se demoraba inicialmente 2 minutos y 15 segundos, y ahora solo se demora 3 segundos. ¡Increíble! ¿Verdad?

Por último, voy a exponer el código por si a alguien le interesa:

En el Form_Load del formulario de captura:

    Dim strTextActualId As String               'para la búsqueda por el Id

    Dim strTextAnteriorId As String

    Dim strTextActualPriApell As String         'para la búsqueda por el primer apellido

    Dim strTextAnteriorPriApell As String

    Dim strTextActualSegApell As String         'para la búsqueda por el segundo apellido

    Dim strTextAnteriorSegApell As String

    Dim strTextActualNombres As String          'para la búsqueda por el nombre

    Dim strTextAnteriorNombres As String

    Dim strTextActualCI As String               'para la búsqueda por el carné de identidad

    Dim strTextAnteriorCI As String

   

    Do While rstPrincipal.EOF = False

        'Id

        strTextActualId = rstPrincipal!IdDatosPers

        If strTextActualId <> strTextAnteriorId Then

            DescomponerId = Split(strAlmacenarId, "\")

            strAlmacenarId = strAlmacenarId & "\" & strTextActualId

        End If

        strTextAnteriorId = strTextActualId

       

        'Primer Apellido

        strTextActualPriApell = rstPrincipal!DatosPersPriApell

        If strTextActualPriApell <> strTextAnteriorPriApell Then

            DescomponerPriApell = Split(strAlmacenarPriApell, "\")

            strAlmacenarPriApell = strAlmacenarPriApell & "\" & strTextActualPriApell

        End If

        strTextAnteriorPriApell = strTextActualPriApell

       

        'Segundo Apellido

        strTextActualSegApell = rstPrincipal!DatosPersSegApell

        If strTextActualSegApell <> strTextAnteriorSegApell Then

            DescomponerSegApell = Split(strAlmacenarSegApell, "\")

            strAlmacenarSegApell = strAlmacenarSegApell & "\" & strTextActualSegApell

        End If

        strTextAnteriorSegApell = strTextActualSegApell

       

        'Nombres

        strTextActualNombres = rstPrincipal!DatosPersNombres

        If strTextActualNombres <> strTextAnteriorNombres Then

            DescomponerNombres = Split(strAlmacenarNombres, "\")

            strAlmacenarNombres = strAlmacenarNombres & "\" & strTextActualNombres

        End If

        strTextAnteriorNombres = strTextActualNombres

       

        'Carné de Identidad

        strTextActualCI = rstPrincipal!DatosPersCI

        If strTextActualCI <> strTextAnteriorCI Then

            DescomponerCI = Split(strAlmacenarCI, "\")

            strAlmacenarCI = strAlmacenarCI & "\" & strTextActualCI

        End If

        strTextAnteriorCI = strTextActualCI

       

        rstPrincipal.MoveNext

    Loop

    'agregamos el separador ("\") al final de la matriz; de lo contrario,

    'el último elemento no se contaría dentro de la matriz en el momento de doscomponerlo

    DescomponerId = Split(strAlmacenarId, "\")

    DescomponerPriApell = Split(strAlmacenarPriApell, "\")

    DescomponerSegApell = Split(strAlmacenarSegApell, "\")

    DescomponerNombres = Split(strAlmacenarNombres, "\")

    DescomponerCI = Split(strAlmacenarCI, "\")

 

En el evento cerrar del formulario de captura:

'eliminamos las matrices

    Set DescomponerId = Nothing

    Set DescomponerPriApell = Nothing

    Set DescomponerSegApell = Nothing

    Set DescomponerNombres = Nothing

    Set DescomponerCI = Nothing

 

En el formulario de búsqueda, donde se cargan los combos, en el Form_Load:

Dim l As Integer

    cboBusqIdDatosPers.Clear

    For l = 1 To UBound(DescomponerId)

        cboBusqIdDatosPers.AddItem DescomponerId(l)

    Next l

   

    Dim iMatriz As Integer      'variable contable para el ciclo de la matriz

    Dim iCombo As Integer       'variable contable para el ciclo del combo

    Dim bolYaEsta As Boolean    'variable que nos avisa si existe coincidencia _

                                 entre los elementos de la matriz y los elementos del combo

   

    'blanqueamos el combo

    cboBusqDatosPersPriApell.Clear

    'realizamos un ciclo a la matriz del primer apellido

    For iMatriz = 1 To UBound(DescomponerPriApell)

        'declaramos la variable a falso

        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 cboBusqDatosPersPriApell.ListCount - 1

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

            If cboBusqDatosPersPriApell.List(iCombo) = DescomponerPriApell(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 cboBusqDatosPersPriApell.AddItem DescomponerPriApell(iMatriz)

    Next iMatriz

   

    cboBusqDatosPersSegApell.Clear

    For iMatriz = 1 To UBound(DescomponerSegApell)

        bolYaEsta = False

        For iCombo = 0 To cboBusqDatosPersSegApell.ListCount - 1

            If cboBusqDatosPersSegApell.List(iCombo) = DescomponerSegApell(iMatriz) Then

                bolYaEsta = True

                Exit For

            End If

        Next iCombo

        If bolYaEsta = False Then cboBusqDatosPersSegApell.AddItem DescomponerSegApell(iMatriz)

    Next iMatriz

   

    cboBusqDatosPersNombres.Clear

    For iMatriz = 1 To UBound(DescomponerNombres)

        bolYaEsta = False

        For iCombo = 0 To cboBusqDatosPersNombres.ListCount - 1

            If cboBusqDatosPersNombres.List(iCombo) = DescomponerNombres(iMatriz) Then

                bolYaEsta = True

                Exit For

            End If

        Next iCombo

        If bolYaEsta = False Then cboBusqDatosPersNombres.AddItem DescomponerNombres(iMatriz)

    Next iMatriz

   

    cboBusqDatosPersCI.Clear

    For l = 1 To UBound(DescomponerCI)

        cboBusqDatosPersCI.AddItem DescomponerCI(l)

    Next l

 

Repito, de esta forma, de 2 minutos y 15 segundos que inicialmente se demoraba la carga de los combos, ahora solo se demoran 3 segundos.

Ojalá la idea le sirva a alguien más.

Saludos
Desde La Habana, Cuba
Medardo
Arriba
VIMIPAS Ver desplegable
Colaborador
Colaborador
Avatar

Unido: 06/Enero/2006
Localización: ESPAÑA
Estado: Sin conexión
Puntos: 5150
Enlace directo a este mensaje Enviado: 22/Octubre/2015 a las 22:52
Hola buenas noches a todos.

Medardo, yo tengo un método para buscar nombres (sobre todo nombres) en mis funciones favoritas. Este es el ejemplo al que me refiero:

http://www.mvp-access.com/foro/buscador-que-sugiere-palabras-mientras-se-escribe_topic80380.html

El objetivo del ejemplo era algo similar (similar en cuanto a velocidad) a lo que hace Google cuando estamos buscando y al mismo tiempo (incluso en caso de errores al digitar lo que buscamos) que se escribe, Google te sugiere.

Para ello, observé que los tiempos de "mi tecleo" (evidentemente me autoexaminé) estaban en una media de 0'050/0'070 segundos por cada tecla que pulsaba. Con esos tiempos no había forma de competir "contra" Access. Estoy hablando de buscar y presentar nombres (y sus posibles correcciones) a la misma velocidad de escritura.

Digo "contra" Access porque la dinámica de Access es: "busco todos los registros", los tengo en un recordset y entonces los presento. Decididamente tuve que olvidar el clásico Formulario (continuo o único) y estudiar otras fórmulas.

En mi ejemplo uso las "colecciones", en un formulario propio que usa 17 filas, y tan rápido es el modo de interactuar con las colecciones que con 43.656 registros de prueba en una tabla, te da tiempo a:

Escribir, buscar, encontrar y presentar los 17 primeros en un tiempo medio de 0'068/0'091 segundos. Y además puedes presentar los que quieras de todos los posibles que haya con el mismo sistema que cuando Access ya los tiene a "todos" controlados. ültimo, primero, ir al registro X. Perdón, edito después de releerme, ya que se me olvidaba, que mientras que se hace todo lo dicho en este mismo párrafo, también se han contado el total de registros que contemplan lo buscado (3.000 o 4.000 registros contados es de lo mas fácil del mundo en ese mismo tiempo que he dicho de 0'068/0'091 segundos). Perdón y gracias de nuevo.

Incluso yo echo de menos en Access en una búsqueda cualquiera, que buscar (en un solo campo hablo) Antonio García García (o varios apellidos iguales) sea mas que imposible. Pues gracias a Collection (lo podrás ver en el ejemplo) es el huevo de colón y la velocidad ya la he comentado.

Yo no llegué a probar los Arrays, que incluso también los tuve en principio a tiro de estudio y es posible que ahora que te he leido tal vez me dedique a ello.

Dejo esto aquí por si te interesa.

Saludos



Editado por VIMIPAS - 22/Octubre/2015 a las 22:55
Gracias
Arriba
 Responder Responder
  Compartir tema   

Ir al foro Permisos de foro Ver desplegable