• Miércoles 15 de Mayo de 2024, 07:31

Autor Tema:  combobox + listbox + relacion con tabla  (Leído 5029 veces)

Rugal_gp

  • Nuevo Miembro
  • *
  • Mensajes: 4
    • Ver Perfil
combobox + listbox + relacion con tabla
« en: Domingo 18 de Octubre de 2009, 09:07 »
0
hola estoy tratando de hacer 1 control de una rentacar como trabajo para taller de programacion estoy recien empezando soy novato en esto asi ke sorry

la cuestion es ke tengo un combo box ke se llena con datos que saco de 1 tabla de mi base :

Tabla : Flota (los campos los he tenido que escribir hacia abajo por que como no pude adjuntar imagen sorry)

patente          
zx4466              
rs5645                                      
etc..                                

modelo
nissan
toyota
lada

disponibilidad
si
si
si

Mi combo solo muestra el campo "modelo"  (nissan,toyota,lada)
cada vez que yo selecciono uno se van agregando a una  Listbox que tengo en mi formulario de esta forma me da posibilidad de arrendar mas de 1 vehiculo por  cliente

1.- Lo que me gustaria hacer es que despues de llenar todo el formulario y pinche el boton "aceptar" me cambie el  campo "si" por un "no" en la columna "disponibilidad" de mi tabla flota (tercera columna) para llevar el control de la disponibilidad de los autos que tengo para arrendar teniendo en cuenta los valores que agregue a la LISTBOX

2.-Una vez que haya cambiado el estado de los autos a "no" y vuelva a abrir el formulario que al combo_box le aparescan solo los autos con estado "si" por que se supone ke los ke tienen "no" ya estan arrendados.

Este es el codigo ke tengo para el combo_box y  me agrega todos los campos que estan  en "modelo" sin filtrar los disponibles y los que no estan disponibles

.................................................. .............................................
Private Sub Form_Load()


Set base_rentacar = OpenDatabase("c:baserentacar.mdb")
Set tabla_rentacar = base_rentacar.OpenRecordset("flota")


Do

cmb_vehiculos.AddItem tabla_rentacar("modelo")
tabla_rentacar.MoveNext

Loop While Not tabla_rentacar.EOF

base_rentacar.Close


End Sub
.................................................. ............................................

Y aqui el codigo ke tengo para agregarle los valores desde el combo a la list

Private Sub cmb_vehiculos_Click()

lst_vehiculos.AddItem cmb_vehiculos

End Sub
..................................................................................................
AYUDA PORFA

Nebire

  • Miembro HIPER activo
  • ****
  • Mensajes: 670
    • Ver Perfil
Re: combobox + listbox + relacion con tabla
« Respuesta #1 en: Domingo 18 de Octubre de 2009, 15:51 »
0
De entrada no me quedaba claro si querías 'controlar un rentacar' o  si querías crear un control de usuario orientado a un rentacar, porq lo que dices en la línea 'estoy tratando de hacer 1 control de una rentacar '.... No obstante como eres principiante y no hay referencias explícitas y no cambia en nada le código que necesitas asumo que es lo primero... hacer un control de un rentacar queriendo indicar controlar un erntacar (en VB hay algo llamado control, de forma que cuando uno dice quiero hacer un control de... da pie a pensar en que se refiere a un control de usuario (que es cosa de programación) frente a un control como acción del verbo controlar...

Hecha la aclaración, paso a explicarte.
Te cuesta lograr lo que quieres porque tu base de datos básicamente está incompleta (amén de que puedas diseñarla mejor, como alegas que sólo es un ejercició para adquirir conocimientos, pasaremos por alto esto último para ceñirnos en completar tu BD), por tanto ahora viene un pequeño 'rollo', explicativo aclarativo que espero que te ilustre.

Una base de datos puede comportarse como sabes para reflejar lo que típicamente se conoce como 'altas' y 'bajas'. Esto de altas y bajas no es otra cosa que cambiar el estado de un dato, y más concretamente (para conocerse como alta y baja) está ceñido a solo 2 estados (a veces a 1 tercero que en tu caso sería conveniente contemplarlo auqnue casi siempre puede ser asumido en uno de los otros 2 estados anteriores... Estos 2 estados como puedes intuir son 'Si' y 'No'; cierto/falso,; 0/1; 0/255; etc... Esto en la práctica implica elegir entre 2 modelos de diseñar el funcionamiento de tu base de datos, el primer modo afecta a un campo de la tabla, el segundo modo afecta a todo el registro, se debe elegir uno u otro modelo independientemente, ahora en situaciones críticas, es más efectivo elegir un modo o el otro de acuerdo a como se utilice la base de datos, cantidad de conexiones, frecuencia de uso, cantidadde registros, cantidad de cambios, datos compartidos entre varios clientes, etc...

Ahora te aclaro estos modos (luego vuelve a repasar este párrafo anterior que te quedará más claro después de leer este otro). Cuando un usuario (de la BD) elige un modelo de vehículo ( ahora ya vamos a referirnos a cosas concretas para que te sea más fácil entenderlo) lo que debemos haceres ir a la base de datos y cambiar (ACTUALIZAR) el estado del modelo elegido (supongo que está regido en base a su matrícula (esto es, Matriicula es la clave principal de esa tabla, si en tu BD de ejemplo sólo tienes modelos, no importa, tanto en cuanto no haya modelos repetidos, si los hay, entonces hay que establecer una diferenciación y para ello lo mejor dado el caso sería incluir un campo matrícula que identifica cada objeto (vehículo) en particular). Es decir si un cliente eligió el modelo X cuando pasas el modelo X al listbox , también debes cambiar el estado para que la BD refleje el nuevo estado a 'NO'.  Para ser más exactos esto debería hacerse sólo cuando el cliente confirma al usuario (digamos que el cliente es el que alquila el vehículo y el usuario el operario de la rentacar que está atendiendo al cliente) que definitivamente se queda con 'esos' modelos. Lo normal es que los clientes estén dudoosos, te digan si, luego, ...añade ese, luego, ...quita aquél, ...este tiene un color feo cambiámelo por el de antes... y así... no vamos a sobrecargar la base de datos con cada cambio de parecer del cliente, sólo lo haremos una vez, y sólo si el cliente al final 'firma y paga' y sólo con los modelos elegidos, el resto de cambios del 'capricho' del cliente, sólo se harán a nivel de interfaz.

NOTA: Supongo que lo que llamas 'patente' es lo que yo designo como 'matrícula'.

Como ves hemos indicado que cambiamos el dato del campo disponible asociado al modelo. (Es decir lo hemos dado de 'baja' cuando el cliente ha elegido definitivamente el modelo X). Esto es suficiente cuando nuestra BD no tiene mucho trabajo. Si nuestra base de datos tiene mucho trabajo exige que en las búsquedas deba filtrar por el campo disponibilidad 'And Flota.Disponibilidad = "si"'... voy a asumir (cosa que nunca me gusta) que el objeto Tabal_rantacar es un objeto AdoDc o AdoDB, entonces en tu bucle Do ... While not ...EOF debes modificar la línea de añadido como te indico:
 
Código: Visual Basic
  1.  
  2. ' Esta línea... :
  3. cmb_vehiculos.AddItem tabla_rentacar("modelo")
  4.  
  5. ' debe fijarse dentro de un condicional, tal que así:
  6. if  tabla_rentacar("modelo").Value="si" then
  7.     cmb_vehiculos.AddItem tabla_rentacar("modelo")
  8. end if
  9.  
  10. ' importante: antes de llenar el combo previamente hay que vaciarlo
  11.  
  12.  

cuando una base de datos va a tener mucho trabajo, es más óptimo tener 2 tablas que contienen los mismo campos (pero el campo dispobilidad ha desaparecido), este campo se ve reflejado ahora en 2 tablas y las tablas se llamarían por ejemplo: FlotaActiva y FlotaInactiva, entonces cuando se de de baja un modelo lo que se haría sería tomar el registro del modelo X y añadirlo a la tabla FlotaInactiva, luego eliminarlo de la tabla FlotaActiva. Y viceversa, cuando el cliente entregue el modelo localizar el modelo en el registro de la tabla FlotaInactiva, copiarlo y añadirlo a la tabla FlotaActiva y luego eliminarlo de la tabla FlotaInactiva. El resultado es que el rendimiento de la BD es mayor (esto se nota cuando la BD tiene mucha carga de trabajo si no es el caso no se nota), por que sólo tiene que buscar sin tener que filtrar, lo mismo cuando vuelcas la tabla a un control, por ejemplo tu combo, no necesitas filtrarlo por 'if  tabla_rentacar("modelo").Value="si"  then', sino que tomarías todos tal como venías haciendo. 10 millones de registros implica 10 millones de preguntas (una por cada registro), si sabemos que la tabla SOLO tiene vehículos disponibles, la pregunta sobra y por tanto nos ahorramos 10 millones de preguntas. Espero que hayas captado la idea.

Te hablaba de un tercer estado, éste estado por ejemplo es modelo: 'Averiado'  y que al caso puede considerarse como 'no' disponible. Nuevamente si manejaras millones de registros y este valor fuera muy grande implicaría un retraso, por ejemplo cuando el cliente entrega el vehículo al localizar el modelo estamos preguntando a vehículos averiados si es el modelo que entrega el cliente, para darlo nuevamente de alta, pero sabemos que nunca vas a ser un vahículo averiado, por eso una tabla llamada FlotaAveriada, trabajaría con respecto de FlotaInactiva de forma similar a lo que hace FlotaActiva con FlotaaInactiva... imagina estos casos: Un cliente ha tenido un golpe contra una farola, una grúa se desplaza y se entrega en el taller, el del taller debe buscar el modelo x en la tabla FlotaInactiva y mudarlo a la tabla FlotaAveriada, y así consta que el Modelo está entregado, si se dejara en FlotaInactiva podría pensarse que elcliente aún lo tiene en su poder, por tanto si se utiliza 3 tablas, sería conveniente cambiar el nombre de la flotaInactiva por el de Flotaalquilada, pués si en un momento queremos conocer el 'estado' de un modelo debe devolver su estado actual si sólo tenemos 2 tablas, estado nos dirá 'si, 'no' están disponibles, pero si queremos por ejemplo saber si un modelo no ha sido entregado o no, esto no es suficiente, los averiados obran en nuestro poder pero estándo inactivos parece que estuvieran alqulados y que el cliente no lo entregó aún, luego realizar la pertinenete factura para cobrar sería complicado determinarlo y puede dar pie a situaciones de equívoco, esto es fácil de evitar si se mantiene una 3ª tabla FlotaAveriada y para clarificar FlotaInactiva sería conveniente cmabiarlo a FlotaAlquilada...

Espero que toda la parrafada, te resulte útil a la hora de diseñar tablas, y si bien para modelos de prácticas y aprendizaje esto no tiene importancia, pero existe la posibilidad de que se convierta en vicio o que uno piense: 'siempre me lo enseñaron así y siempre me funcionó' y por ello tener bajo rendimiento cuando se nos presenta un caso de una BD con mucho trabajo.

También quiero aclararte otro punto, al trabajar con ADODC ( ADODB, ADOR,etc...), es conveniente hacer que el recordset esté ordenado, porque entonces pueden hacerse búsquedas binarias y entonces si que el rendimiento se eleva, además en el uso de 'controles dependientes', como es tu caso (al usar un combo), puedes referirte a registros en el combo que coinciden con registros en el recordset, lo que significa que puedes emplear su índice (en el recordset sería leer o establecer absoluteposition) que es todavía más efectivo que buscar incluso aunque sea una búsqueda binaria. Para que esto sea así, tu combo también debe tener la propiedad sort establecida a true. (sólo el combo que recibe el volcado de la BD no el combo donde se transfieren los modelos que el cliente elige, éste es mejor que el orden sea en el que se introducen.

Para ordenar el recordset tienes que modificar la línea de conexión, seguramente tengas algo como 'Select * from Flota' pués ahora deberías cambiarlo a: 'Select * from Flota OrderBy Modelo' ,( porque es el modelo lo que añades al combo).

Para que esto último se aplique correctamente, es necesario tener en cuenta otro tipo de cosas, por ejemplo si el recordset aloja tanto los modelos disponibles como los que no, el índice del combo no reflejará correctamente el índice del recordset si lo hemos filtrado, entonces tenemos 3 soluciones posibles:
1 O bien mantenemos 2 tablas (como se indicó más arriba)  .. es lo más fácil y lo más cómodo.
2 O bien eliminamos el filtro al obtener los ítems del recordset para añadirlos al combo, pero a cambio tenemos 'desactivar' los modelos nos disponibles.
3 O bien utilizamos la propiedad Itemdata (del combo) , para retener el índice posicional dentro del recordset.

Termino el post detallando acerca de estas 3 posibilidades:
1  Al mantener tablas separadas para los elementos disponibles y  los no disponibles, se toma el recordset completo, no necesitamos filtrarlo y por tanto todo lo dicho sobre sortby (para el recordset) y sorted (para el combo) es válido.

2 Dado que un combo no permite 'desactivar' elementos individuales, deberíamos remplazar el combobox por un listbox y a dicho listbox cambiar la propiedad style a Checkbox, al rellenar la lista lo que haríamos sería seleccionar el elemento indicando si el modelo está disponible o no. Esto se debe complementar con un filtro, de modo que cuando el cliente elija un modelo de verificarse que no sea un elemento 'no seleccionado'. Algo de código para recoger este caso sería...
Código: Visual Basic
  1.  
  2. public function RellenarListamodelos as boolean
  3.     dim k as long
  4.     if not (tabla_rentacar is nothing) then
  5.         tabla_rentacar.movefirst
  6.         lista_vehiculos.clear    ' ojo: hemos cambiado un combo por un list, en el combo style tiene diferente significado y no tiene propiedad selected
  7.         do While Not tabla_rentacar.EOF
  8.             lista_vehiculos.AddItem tabla_rentacar("modelo")
  9.                 if  tabla_rentacar("modelo").Value="si" then lista_vehiculos.Selected(k)=true
  10.             k=k +1
  11.            tabla_rentacar.MoveNext
  12.         Loop
  13.         RellenarListamodelos =true
  14.     End if
  15. end sub
  16.  
  17.  
Este 2º método tiene en contra que al mostrar modelos tanto disponibles como no, despista al usuario, hace la lista más larga de lo necesario (imagina 120 modelos seguidos no disponibles, el usuario se cansaría de hacer scroll para localizar modelos disponibles).

3  Este método es el más sencillo de aplicar tal como tiene la Bd (además en este podrías omitir ordenar el combo y el recordset, aunque si hay que hacer búsquedas en el recordset (moverse de modo diferente a movenext, moverfirst, etc..., esto es usando 'find'), entonces siempre interesará tenerlo ordenado para poder hacer búsquedas binarias.), de entrada seguimos fltrando , el combo sólo se rellena con modelos disponibles tal como te indicaba en los primeros códigos... Para vincular correctamente los elementos del combo junto con los registros del recordset, utilizamos la propiedad itemdata del combo (list) que sirve precisamente para esto.
Código: Visual Basic
  1.  
  2. public function RellenarListamodelos as boolean
  3.     dim k as long
  4.     if not (tabla_rentacar is nothing) then
  5.         tabla_rentacar.movefirst
  6.         cmb_vehiculos.clear
  7.         k=0
  8.         do While Not tabla_rentacar.EOF
  9.             if  tabla_rentacar("modelo").Value="si" then
  10.                 cmb_vehiculos.AddItem tabla_rentacar("modelo")
  11.                 cmb_vehiculos.itemdata(cmb_vehiculos.listcount)-1)=k
  12.             end if
  13.             k=k +1
  14.            tabla_rentacar.MoveNext
  15.         Loop
  16.         RellenarListamodelos =true
  17.     End if
  18. end sub
  19.  
  20.  

Usando este 3º modo, cuando copiemos el valor del combo al listbox que ha elegido el cliente también debemos copiar el valor de itemdata. Cuando el cliente finalmente pulse el botón aceptar (vamos que paga y alguila los modelos elegidos) es cuando actualizamos y para ello usamos los itemdata que reflejan el nº de registro del recordset. Un posible código (simplificado) que hace esto sería:
Código: Visual Basic
  1.  
  2. ' dar de baja los modelos elegidos por el cliente
  3. Private Sub ComAlquilar_Click()
  4.     Dim k As Long
  5.    
  6.     For k = 0 To Combo1.ListCount
  7.        ' nos movemos al registro que refiere al modelo que eligió el usuario
  8.        tabla_rentacar.absoluteposition = Combo1.ItemData(k) ' ojo: no confundir itemdata con listindex
  9.        
  10.        ' cambiamos el valor del campo...
  11.        tabla_rentacar.fields("modelo").Value = "no"
  12.     Next
  13.    
  14.     ' actualizar de nuevo el combo para que sólo contenga modelos disponibles
  15.     Call RellenarListamodelos
  16. End Sub
  17.  
  18.  
Esto sólo funcionará bien si el recordset no ha sido modificado, si se eliminaron o añadieron registros, no funcionará en dicho caso habrá que moverse por el recordset usando 'find' para posicionarse sobre el registro correcto, para hacer el cambio oportuno.

Hay muchas más cosas que decir, pero la verdad, me da pereza responder temas de bases de datos porque es tan amplio y cada circunstancia lleva aparejada tantas condiciones y los posteadores omiten tantos datos  y demás cosas que una pregunta simple por un supuesto error se acaba convierto en una cacería de errores por lo general por falta de formación y los posts se hacen larguísimos para explicar los entresijos de cada detalle con claridad... para muestra este mismo post.

Saludos.
«Ma non troppo»
----> ModoVacaciones = False<----

Rugal_gp

  • Nuevo Miembro
  • *
  • Mensajes: 4
    • Ver Perfil
Re: combobox + listbox + relacion con tabla
« Respuesta #2 en: Lunes 19 de Octubre de 2009, 04:59 »
0
Muxas gracias Master me has ayudado un monton decidi tomar la opcion mas sana que fue la de crear 2 tablas con autos disponibles y los ke no y  eliminar el campo estado
todo caso muchas gracias por tu paciencia y tiempo y disculpa la demora en contestar pero estube varias horas completando todo lo demas ahora ke si el profe me la bota volvere a molestar  :brickwall: pero ya con mas confianza por ke se ke aca contesta por ke este mismo post lo mande a varios foros y no me  contestaron muxas gracias amigo. :good: