Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   OOP (https://www.clubdelphi.com/foros/forumdisplay.php?f=5)
-   -   Ayuda con un CheckListBox (https://www.clubdelphi.com/foros/showthread.php?t=91248)

Belen12 12-12-2016 00:46:29

Ayuda con un CheckListBox
 
1 Archivos Adjunto(s)
Hola e realizado una pregunta similar antes ( que logre solucionar gracias a ustedes) ahora lo que necesito es realizar una mejora. Resulta que tengo un formulario donde se listan empleados y estos tienen puestos de trabajos. Yo al selecionar uno realizo la modificacion abro otro formulario en el cual se encuentra un listbox que lista sus puestos de trabajo.este se carga a travez de una consulta de un query. lo que sucede es lo siguiente realize una consulta y cuando se carga ese listbox y se ponen en check sus puestos de trabajo. Pero yo lo que necesito es que se carguen todos los puestos y luego se pongan en check los que el tiene no se si me doy a entender. Yo lo que eh intentado es hacer 2 consultas una para llenar todos los puestos y otra para luego poner en true segun el puesto que tengan. El problema viene aqui cuando se cargan los puesto de ese empleado en check se crea un duplicado es decir por ejemplo si uno es vendedor en list box se carga un puesto vendedor y otro puesto vendedor pero este en check.

Código Delphi [-]
begin

   fempleados := tfempleados.Create(self) ;
   fmodulo.tEmpleados.Active:=True;
// Con este cargo primero todos los puesto//
   fmodulo.qGeneral.Close;
   fmodulo.qGeneral.SQL.Clear;
   fmodulo.qGeneral.SQL.Add('select * from puesto');
   fmodulo.qGeneral.SQL.Add('where estadopuesto=1');
   fmodulo.qGeneral.Open;
    while not fmodulo.qGeneral.Eof do
    begin
        fEmpleados.CheckListBox1.Items.AddObject(
        fmodulo.qGeneral.FieldByName('nombrepuesto').AsString,
        TObject(fmodulo.qGeneral.FieldByName('idpuesto').AsInteger));
      fmodulo.qGeneral.Next;
    end;

// esto lo uso para abrir los dbedit en forma de edit
if fModulo.tEmpleados.Locate('idempleado',fmodulo.qEmpleados['idempleado'],[]) then;        //localiza un registro
 begin
  empleado:= fmodulo.qEmpleados.FieldByName('idempleado').AsInteger;
  fmodulo.tEmpleados.Edit;
/// de aqui uso la consulta para buscar el puesto que le corresponde a ese empleado
       fmodulo.qPuestos.Close;
       fmodulo.qPuestos.SQL.Clear;
       fmodulo.qPuestos.SQL.Add('select * from puesto');
       fmodulo.qPuestos.SQL.Add('inner join asignado on asignado.idpuesto=puesto.idpuesto');
       fmodulo.qPuestos.SQL.Add('inner join empleados on empleados.idempleado=asignado.idempleado');
       fmodulo.qPuestos.SQL.Add('where empleados.idempleado= :id ');
       fmodulo.qPuestos.ParamByName('id').AsInteger:= empleado;
       fmodulo.qPuestos.Open;
       if not fmodulo.qPuestos.IsEmpty then
       begin
         fmodulo.qPuestos.First;

         while not fmodulo.qPuestos.Eof do
         begin
          fempleados.CheckListBox1.Items.AddObject(
          fmodulo.qPuestos.FieldByName('nombrepuesto').AsString,
          TObject(fmodulo.qPuestos.FieldByName('idpuesto').AsInteger)); // e intentado sacando esta linea ya que es la que me carga el doble registro
                                                          // pero si la saco me marca en check solo el ultimo registro y si la dejo me pone el duplicado 
                                                                                                  

          fempleados.CheckListBox1.Checked[fempleados.CheckListBox1.Items.Count-1]:= true; //este lo uso para poner el check
          fmodulo.qPuestos.Next;
       end;
       end;
 end;
  fempleados.Caption:= 'Modificacion de Empleados' ;
 fempleados.ShowModal;

 fmodulo.tEmpleados.Active:=False;
 fmodulo.qEmpleados.Refresh;
end;

alguna ayuda? no se si mi problema esta en la doble consulta. si es asi como podria realizar solo una y cargar lo que necesito. Aclaro que yo agregue la primera consulta para traer tambien los puestos que ese empleado no tiene ya que realizando la modificacion le doy la opcion al usuario de asignarle otro puesto si lo desea- Dejo una imagen espero que se vea bien para aclarar mas el problema que se presenta gracias por la ayuda desde ya

Neftali [Germán.Estévez] 12-12-2016 09:31:53

Si lanzas la consulta que estás lanzando para rellenar los puestos directamente contra la Base de Datos, ¿Te salen duplicados?

Belen12 13-12-2016 05:06:51

Mira
 
Cita:

Empezado por Neftali (Mensaje 511699)
Si lanzas la consulta que estás lanzando para rellenar los puestos directamente contra la Base de Datos, ¿Te salen duplicados?

mira a ver si me doy a entender. la primera consulta usandola solo me trae todos los puestos. por otro lado la segunda consulta me trae los puestos con el check en true. Ambas consulta lanzadas por si solas no me dan duplicado me andan bien ya lo comprobe.El tema es que al unir las 2 en ves de traerme todos(que haria la primera) y y poner solo en true los que le corresponde al seleccionado(esto en teoria deberia hacer la segunda) la segunda consulta me llena un nuevo puesto y este lo deja en check y aqui es donde se me produce el duplicado. Intente sacando la siguiente linea
Código Delphi [-]
 fempleados.CheckListBox1.Items.AddObject( fmodulo.qPuestos.FieldByName('nombrepuesto').AsString,         TObject(fmodulo.qPuestos.FieldByName('idpuesto').AsInteger));
que es la que me llena el duplicado pero al hacerlo me deja en true solo el ultimo registro :/ gracias por responder

ecfisa 13-12-2016 07:20:35

Hola.

Si te entendí bien podrías hacer algo similar a esto:
Código Delphi [-]
...
procedure TForm1.FormCreate(Sender: TObject);
begin
  // Cargar en el CheckListBox los cargos de la tabla PUESTO
  unQuery.Close;
  unQuery.SQL.Text := 'SELECT ID, NOMBREPUESTO FROM PUESTO';
  unQuery.Open;
  while not unQuery.Eof do
  begin
    CheckListBox1.AddItem( unQuery.FieldByName( 'NOMBREPUESTO' ).AsString,
      TObject(unQuery.FieldByName ( 'ID' ).AsInteger ) );
    unQuery.Next;
  end;
  unQuery.Close;
end;

procedure TForm1.ActualizarPuestos( const EmpID: Integer );
var
  i : Integer;
begin
  // Quitar tildes a los items del CheckListBox 
  for i := 0 to CheckListBox1.Items.Count - 1 do
    CheckListBox1.Checked[i] := False;

  // Seleccionar los puestos asignados al empleado EmpID
  unQuery.Close;
  unQuery.SQL.Clear;
  unQuery.SQL.Add( 'SELECT P.ID AS PUESTOID FROM EMPLEADOS E' );
  unQuery.SQL.Add( 'INNER JOIN ASIGNADOS A ON E.ID = A.EMPLEADO_ID' );
  unQuery.SQL.Add( 'INNER JOIN PUESTOS P ON P.ID = A.PUESTO_ID' );
  unQuery.SQL.Add( 'AND E.ID = :EMPID' );
  unQuery.ParamByName( 'EMPID' ).AsInteger := EmpID;
  unQuery.Open;

  // Poner tildes en aquellos cargos que EmpID tenga asignados
  while not unQuery.Eof do
  begin
    i := CheckListBox1.Items.IndexOfObject(
      TObject( unQuery.FieldByName( 'PUESTOID' ).AsInteger ) );
    if i <> -1 then
      CheckListBox1.Checked[i] := True;
    unQuery.Next;
  end;
end;
...

Llamada ejemplo:
Código Delphi [-]
begin
  ActualizarPuestos( SpinEdit1.Value );
  ...
De ese modo se carga una sola vez la totalidad de puestos en el CheckListBox y se marcan con un tilde los puestos que tiene asignados el empleado cuyo ID se le envía al procedimiento ActualizarPuestos.

Espero haberte interpretado bien...

Saludos :)

Belen12 14-12-2016 06:47:49

gracias
 
Cita:

Empezado por ecfisa (Mensaje 511706)
Hola.

Si te entendí bien podrías hacer algo similar a esto:
Código Delphi [-]
...
procedure TForm1.FormCreate(Sender: TObject);
begin
  // Cargar en el CheckListBox los cargos de la tabla PUESTO
  unQuery.Close;
  unQuery.SQL.Text := 'SELECT ID, NOMBREPUESTO FROM PUESTO';
  unQuery.Open;
  while not unQuery.Eof do
  begin
    CheckListBox1.AddItem( unQuery.FieldByName( 'NOMBREPUESTO' ).AsString,
      TObject(unQuery.FieldByName ( 'ID' ).AsInteger ) );
    unQuery.Next;
  end;
  unQuery.Close;
end;

procedure TForm1.ActualizarPuestos( const EmpID: Integer );
var
  i : Integer;
begin
  // Quitar tildes a los items del CheckListBox 
  for i := 0 to CheckListBox1.Items.Count - 1 do
    CheckListBox1.Checked[i] := False;

  // Seleccionar los puestos asignados al empleado EmpID
  unQuery.Close;
  unQuery.SQL.Clear;
  unQuery.SQL.Add( 'SELECT P.ID AS PUESTOID FROM EMPLEADOS E' );
  unQuery.SQL.Add( 'INNER JOIN ASIGNADOS A ON E.ID = A.EMPLEADO_ID' );
  unQuery.SQL.Add( 'INNER JOIN PUESTOS P ON P.ID = A.PUESTO_ID' );
  unQuery.SQL.Add( 'AND E.ID = :EMPID' );
  unQuery.ParamByName( 'EMPID' ).AsInteger := EmpID;
  unQuery.Open;

  // Poner tildes en aquellos cargos que EmpID tenga asignados
  while not unQuery.Eof do
  begin
    i := CheckListBox1.Items.IndexOfObject(
      TObject( unQuery.FieldByName( 'PUESTOID' ).AsInteger ) );
    if i <> -1 then
      CheckListBox1.Checked[i] := True;
    unQuery.Next;
  end;
end;
...

Llamada ejemplo:
Código Delphi [-]
begin
  ActualizarPuestos( SpinEdit1.Value );
  ...
De ese modo se carga una sola vez la totalidad de puestos en el CheckListBox y se marcan con un tilde los puestos que tiene asignados el empleado cuyo ID se le envía al procedimiento ActualizarPuestos.

Espero haberte interpretado bien...

Saludos :)

gracias me sirvio de mucho ya me funciona como quiero. Mira una ultima cosa ahora ya que tengo esto procedo a realizar el post de la modificacion. y cuando hacia el insert primero usaba el siguiente codigo en el boton aceptar
Código Delphi [-]
qEmpleados['fechanacimiento']:=dtFecha.Date
qEmpleados.Post
for i:= 0 to CheckListBox1.Items.Count-1 do
 begin
   if CheckListBox1.Checked[i] then
     begin
      tAsignados.Insert;
      tAsignado.FielbyName('idempleado').AsInteger:= qEmpleados.FielbyName('idempleado').AsInteger; 
      tAsignado.FielbyName('idpuesto').AsInteger:= Integer(CheckListBox1.Items.Objects[i]) ;
      tAsignados.Post;
end;
end;
y al realizar la modificacion cambio tAsignados.Insert lo cambio a Edit y uso el mismo codigo lo que sucede es que no me modifica nada y solo me inserta dos veces el mismo valor por ejemplo si marco 2 puestos nuevos(cajeros por ej) y este ya es vendedor se me carga 3 puestos de vendedores alguna idea por que sucede esto ? ya revice el codigo de pie a cabeza y no tengo ningun insert en ningun lado para que me genere este problema. sera problema en el codigo que postie ?
gracias por toda la ayuda de verdad

ecfisa 14-12-2016 21:24:13

Hola.

Como lo estas trabajando, me parece que tendrás que "limpiar" todos los puestos anteriores de un empleado y luego agregar los nuevos cargos, algo parecido a esto:
Código Delphi [-]
procedure TForm1.ModificarPuestos(const EmpID: Integer);
var
  i,Pid: Integer;
begin
  // Borrar los puestos anteriores de un empleado
  unQuery.Close;
  unQuery.SQL.Text := 'DELETE FROM ASIGNADO WHERE EMPLEADO_ID = :EID';
  unQuery.ParamByName('EID').AsInteger := EmpID;
  unQuery.ExecSQL;

  // Agregar los nuevos valores del CheckListBox
  unQuery.Close;
  unQuery.SQL.Clear;
  unQuery.SQL.Add('INSERT INTO ASIGNADO( EMPLEADO_ID, PUESTO_ID )');
  unQuery.SQL.Add('VALUES( :EID, :PID )');
  unQuery.Prepare;
  try
    for i := 0 to CheckListBox1.Items.Count - 1 do
      if CheckListBox1.Checked[i] then
      begin
        Pid := Integer(CheckListBox1.Items.Objects[i]);
        unQuery.ParamByName('EID').AsInteger := EmpID;
        unQuery.ParamByName('PID').AsInteger := Pid;
        unQuery.ExecSQL;
      end;
  finally
    unQuery.UnPrepare;
  end;
end;
Llamada ejemplo:
Código Delphi [-]
begin
  ModificarPuestos( SpinEdit1.Value );
...

Saludos :)

Belen12 15-12-2016 05:59:34

Cita:

Empezado por ecfisa (Mensaje 511776)
Hola.

Como lo estas trabajando, me parece que tendrás que "limpiar" todos los puestos anteriores de un empleado y luego agregar los nuevos cargos, algo parecido a esto:
Código Delphi [-]
procedure TForm1.ModificarPuestos(const EmpID: Integer);
var
  i,Pid: Integer;
begin
  // Borrar los puestos anteriores de un empleado
  unQuery.Close;
  unQuery.SQL.Text := 'DELETE FROM ASIGNADO WHERE EMPLEADO_ID = :EID';
  unQuery.ParamByName('EID').AsInteger := EmpID;
  unQuery.ExecSQL;

  // Agregar los nuevos valores del CheckListBox
  unQuery.Close;
  unQuery.SQL.Clear;
  unQuery.SQL.Add('INSERT INTO ASIGNADO( EMPLEADO_ID, PUESTO_ID )');
  unQuery.SQL.Add('VALUES( :EID, :PID )');
  unQuery.Prepare;
  try
    for i := 0 to CheckListBox1.Items.Count - 1 do
      if CheckListBox1.Checked[i] then
      begin
        Pid := Integer(CheckListBox1.Items.Objects[i]);
        unQuery.ParamByName('EID').AsInteger := EmpID;
        unQuery.ParamByName('PID').AsInteger := Pid;
        unQuery.ExecSQL;
      end;
  finally
    unQuery.UnPrepare;
  end;
end;
Llamada ejemplo:
Código Delphi [-]
begin
  ModificarPuestos( SpinEdit1.Value );
...

Saludos :)

muchas gracias me sirvio de mucho anda perfecto, muchas gracias por tomarte el tiempo y ayudarme.


La franja horaria es GMT +2. Ahora son las 13:08:31.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi