PDA

Ver la Versión Completa : Añadir elementos sin repetir


MaMu
25-05-2007, 17:57:38
Hola, yo relleno un ComboBox, con elementos de una tabla, de la siguiente manera:


procedure TPedidos.ADOQuery2AfterOpen(DataSet: TDataSet);
var i:integer;
begin
ComboBox2.Clear;
for i:=0 to ADOQuery2.RecordCount-1 do
begin
ComboBox2.Items.Add(ADOQuery2.FieldByName('servicio').AsString);
ADOQuery2.Next;
end;
end;


Pero por ejemplo, tengo servicios con el mismo nombre, pero con otros valores de campo diferentes, como ser:

(CAMPOS) SERVICIO VARIABLE
(VALORES) "Limpieza" "Alfombra"
"Limpieza" "Cortina"
"Limpieza" ...etc....

Yo lo que hago es a su vez, rellenar otro ComboBox, con los valores de VARIABLE segun el SERVICIO seleccionado, y me funciona perfectamente.
Mi pregunta es la siguiente:

- Como puedo agregar elementos a un ComboBox sin que estos se repitan si son iguales??? Por ejemplo si hay un servicio "Limpieza" con 10 variables, quiero que se agregue solamente uno solo "Limpieza" puesto a que en el otro ComboBox ya estoy cargando sus variables.
El segundo ComboBox lo relleno de la siguiente manera, sin ningun problema:


procedure TPedidos.ComboBox2Change(Sender: TObject);
begin
ADOQuery2.Locate('servicio',ComboBox2.Text,[loPartialKey]);
ADOQuery8.Close;
ADOQuery8.SQL.Clear;
ADOQuery8.SQL.Add('select * from servicios where servicio like '''+ComboBox2.Text+'%''');
ADOQuery8.ExecSQL;
ADOQuery8.Open;
end;


Realmente no se como hacer para agregar un elemento sin que se repita si hay 2 o mas con el mismo nombre, estuve intentado cosas, pero por ahi me muestra la mitad, algunos los repite, otros ni los muestra.... en fin

Si alguien me puede dar una mano se lo agradecere.

Saludos y Gracias

Delphius
25-05-2007, 18:07:13
Puede que diga una tontera pero:

¿En la consulta que lanzas para llenar el combo de los servicios tienes la clausura DISTINCT?

Ahora, no dices en que base de datos estás trabajando...

EDITO:
Me confunde tu código. Por lo que veo, en tu primer código lo que haces es llenar los servicios en el combobox2. Pero en el código siguiente estás consultando los servicios que concidan con el texto seleccionado de dicho combo.

A mi modo de entender, tu código dice una cosa pero tu escrito dice otra:

Por ejemplo si hay un servicio "Limpieza" con 10 variables, quiero que se agregue solamente uno solo "Limpieza" puesto a que en el otro ComboBox ya estoy cargando sus variables.
El segundo ComboBox lo relleno de la siguiente manera, sin ningun problema:


¿Podrías aclararme mejor? Estoy confundido...


Saludos,

Kenobi
25-05-2007, 18:07:15
hola, al menos en teoria lo que debes hacer es antes de introducir el elemento chequeando que no este y si es asi introducirlo....

yo haria una function llamada buscar en combo

function TFrmCancelRetiroLotes.Buscar_en_combo(Elemento: string): boolean;
var
i:integer;
encontrado:boolean;
begin
encontrado:=false;
for i:=0 to combo.Items.Count-1 do
begin
if Elemento = combo.Items.Item[i].Caption then
begin
encontrado:=true;
break;
end;
end;

Result:=encontrado;

end;

luego antes de introducir el elemento

haria algo asi

Encontrado:=buscar_en_Combo(TEdit.text);
if not Encontrado then
begin
//aca el codigo para introducir el elemento eso ya lo tienes ......
end;


Espero que te sirva....

Saludos....

Robert01
25-05-2007, 18:11:02
Hola

Si no me equivoco este anda perfectamente es para dos listbox, no debería haber problemas en aplicarlo a un combobox.


procedure TAnalisisCls.Lista1Click(Sender: TObject);

var
index, i : integer;
begin
index := Lista1.Items.Count;
i := 0;
while i < index do
begin
if (ListaPob1.Selected[i]) then
begin
Lista2.Items.Add(Lista1.Items.Strings[i]);
Lista1.Items.Delete(i);
index := index - 1;
i := 0;
end
else i := i + 1;
end;
end;

procedure TAnalisisCls.Lista2Click(Sender: TObject);
var
index: integer;
begin
index := Lista2.ItemIndex;
Lista1.Items.Add(Lista2.Items.Strings[index]);
Lista2.Items.Delete(index);
//InBtn.Enabled := true;
//if Lista2.Items.Count = 0 then OutBtn.Enabled := false;
end;

Saludos

MaMu
25-05-2007, 18:24:01
¿Podrías aclararme mejor? Estoy confundido...
Saludos,

Si, por ahi me explaye demaciado, lo que quiero saber simplemente, es como agregar elementos a un ComboBox sin que se repitan, osea que si dos elementos tienen el mismo nombre, solo agregue uno de ellos.

Saludos

Delphius
25-05-2007, 18:34:52
Pues como te dije, en la consulta deberías poner la clausura DISTINCT. Con esto no devolvería los repetidos.

Tan solo deberías hacer:

ComboBox2.Items.Add(ADOQuery2.FieldByName('servicio').AsString);

un SQL como esto:

SELECT DISTINCT nombre_servicio
FROM servicios

Saludos,

jhonny
25-05-2007, 18:36:04
Yo lo haría asi, asumiendo que Edit1 es el componente que usaras para introducir datos a ese ComboBox1:

if ComboBox1.Items.IndexOf(Edit1.text) <> -1 then //IndexOf devuelve la posición en la que se encuentra el parámetro que se paso, y si no existe pues devuelve -1
begin
//Introduces el codigo correspondiente...
end;

jhonny
25-05-2007, 18:40:34
Esto me pasa por no leer bien la cuestión y andar de nuevo con mis prisas, si sigue el consejo de Delphius sera mas eficiente pues el sql traerá los datos sin repetirlos...

Mi ejemplo te sirve por ejemplo, en caso de que estuvieras alimentando los datos desde un Edit o algo por el estilo.

MaMu
25-05-2007, 18:41:05
Pues como te dije, en la consulta deberías poner la clausura DISTINCT. Con esto no devolvería los repetidos.

Tan solo deberías hacer:


Código Delphi [-] (http://www.clubdelphi.com/foros/#)ComboBox2.Items.Add(ADOQuery2.FieldByName('servicio').AsString);



un SQL como esto:


Código SQL [-] (http://www.clubdelphi.com/foros/#)SELECT DISTINCT nombre_servicio
FROM servicios




Saludos,



Asi fue como hice:


select distinct servicios.servicio from servicios


pero me salta: List Index out of bounds(3)

Saludos

MaMu
25-05-2007, 19:00:45
SOLUCIONADO


Lo solucioné, el error estaba en la sintaxis SQL, ya que justamemte en la tabla servicios, tenia dos campos, uno servicio y el otro servicios, y los consulte invertidos, eso era todo. Por las demas respuestas estan muy buenas y me son de mucha utilidad, ya que no siempre relleno con datos de una base de datos. Archivado.

Saludos y Gracias

Robert01
25-05-2007, 19:20:32
Hola

No me di cuenta que estabas trabajando con bases de datos, disculpame por enviar código que no es lo que necesitabas.
Me alegra que hayas solucionado el problema.

Saludos

ciskokkid
21-10-2015, 17:58:18
no quiero decir que las formas anteriores de solucionarlo no son validas, solo quiero aportar una forma diferente de hacerlo,
llegue hasta aqui buscando como llenar un combobox desde un clientdataset, no me apetece hacer otra consulta sql con distinct porque estoy partiendo del hecho que ya tengo la informacion en un clientdataset, solo quiero que el combobox coincida con la informacion del clientdataset que estoy mostrando en un grid

este es mi codigo



begin
// hago la consulta , el clientdataset obtiene la informacion del query a traves de un datasetprovider
adoquery1.Close;
adoquery1.SQL.Text:='select c.sucursal, c.id, c.mov, c.movid, c.fechaemision ' +
' , c.proveedor,prov.nombre , c.usuario, c.referencia, ' +
' c.importe, c.moneda, c.tipocambio, c.condicion, c.autorizacion' +
' from compra c ' +
' join prov on prov.proveedor=c.proveedor ' +
' where c.mov=' + quotedstr('ECN') +
' and c.estatus=' + quotedstr('SINAFECTAR') +
' order by c.sucursal,c.proveedor';
adoquery1.Prepared:=true;
adoquery1.Open;

// ahora limpio el combobox, recorro el clientdataset y simplemente voy comprobando si el valor "usuario"
// no esta en el combo lo agrego

cbUsuario.clear;
cbUsuario.Items.Add('TODOS'); // este sera el primer valor
clientdataset1.First;
while not clientdataset1.Eof do
begin
if cbUsuario.items.indexOf(clientdataset1.FieldByName('usuario').AsString)<=0 then
cbUsuario.Items.Add(clientdataset1.fieldByName('usuario').asstring);
clientdataset1.Next;
end;
cbUsuario.ItemIndex:=0; // para que por default ponga por defecto el primer valor
cbUsuario.style:=csDropDownList; // para que el usuario no agregue mas valores al combo

end


la informacon consultada son pocos registros, no mas de 50, de esta manera evito enviar otra consulta por separada al servidor sql

AgustinOrtu
21-10-2015, 21:17:40
Para que pones a Prepared := True el query?
Otra cosa, TStrings ya implementa esta funcionalidad, y es configurable mediante las propiedades Duplicates (http://docs.embarcadero.com/products/rad_studio/delphiAndcpp2009/HelpUpdate2/EN/html/delphivclwin32/Classes_TStringList_Duplicates.html) y CaseSensitive (http://docs.embarcadero.com/products/rad_studio/delphiAndcpp2009/HelpUpdate2/EN/html/delphivclwin32/Classes_TStringList_CaseSensitive.html)

Por otro lado la solucion es apta para cualquier TStrings, el ComboBox tiene poco que ver aca