PDA

Ver la Versión Completa : Buscar componentes


mosorio
25-05-2003, 14:01:38
Hola,
Quisiera que me ayudaran en lo siguiente:
Quiero colocarle color a los componentes que dependiendo de su fuente de datos verificar si son requeridos y colocarle un color diferente.
Estoy haciendo un ciclo donde busco en el datasource y verificando su propiedad required lo asigno a un memo para hacer pruebas y selecciona los que son, pero al asignarle el color es donde me lio. Quisiera hacer lo siguiente, si es factible, cuando encuentre el primer campo que sea requerido, inmediatamente buscar en el formulario el componente que este asociado al campo pero no se como hacerlo, la funcion de findcomponente no sabría como implementarla para esto. No se si me puedan ayudar. De todas formas dejo la inquietud para ver si sale alguna idea.

Gracias de antemano.

El codigo que utilizo es este, claro es una idea


procedure TfrmDatos1.ColorCampoRequerido;
var
i, j: Integer;

begin
for i := 0 to DataSource.DataSet.Fields.Count - 1 do
if DataSource.DataSet.FieldDefs.Items[i].Required then
begin
memo1.Lines.Add(DataSource.DataSet.FieldDefs.Items[i].Name);
for j := 0 to ComponentCount - 1 do
begin
if Components[j].ClassNameIs('TDBEdit') then
begin
(Components[j] as TDBEdit).Color := clLime;
Continue;
end;

if Components[j].ClassNameIs('TDBMemo') then
begin
(Components[j] as TDBMemo).Color := clLime;
Continue;
end;
end;
end;
end;

marcoszorrilla
25-05-2003, 16:23:24
Prueba con este ejemplo que acabo de preparar y verás como funciona.

procedure TForm1.Button1Click(Sender: TObject);
var
I,J:Integer;
begin
for i := 0 to DataSource1.DataSet.Fields.Count - 1 do
begin
if DataSource1.DataSet.FieldDefs.Items[i].Required then
begin
ShowMessage(DataSource1.DataSet.FieldDefs.Items[i].Name +'Requerido');
for j := 0 to ComponentCount - 1 do
begin
if Components[j].ClassNameIs('TDBEdit') then
begin
If DataSource1.DataSet.FieldDefs.Items[i].Name =(Components[j] as TDBEdit).DataField then
(Components[j] as TDBEdit).Color := clLime;
end;
end;
end;
end;


end;

Un Saludo.

mosorio
27-05-2003, 10:22:51
Hola marcos,
He copiado el codigo que me has enviado, y al intentar ejecutarlo me da un error de fuera de indice, no se si esto esta ocurriendo por que tengo un campo calculado en el editor de campos del cds que creo que es lo más certado, tendría que mirar como evitar o eludir este tipo de campos, alguna propiedad especifica que indique que es calculado o de busqueda que es el que tengo.

Gracias

marcoszorrilla
27-05-2003, 15:34:23
De momento no le encuentro solución, porque accede a una matriz formada por los campos persistentes.

Ahora bien, si no añadimos ningún campo real y por ejemplo 3 calculados, accederá a los 3 primeros campos reales del Dataset si los hubiera.

Luego el problema surge cuando añadimos todos los campos reales y un calculado entonces resulta que tenemos una matriz con por ejemplo 21 campos de los cuales solamente existen 20, ya que el calculado no existe en la tabla.

Aquí viene el error al llegar al elmento 21 que no tiene correspondencia.

El error se produce por acceder al elemento 21, que no existe en el DataSet.

Nota: Cuando digo real, quiero decir que el campo existe en la tabla, no me estoy refiriendo a un tipo de datos.

Un Saludo.

marcoszorrilla
27-05-2003, 16:49:13
Bueno despues de algunas pruebas he logrado circumvenir al DataSet, lo que he hecho es ver la manera de conocer el número real de campos que hay en la tabla, la única manera que he econtrado y que funciona, es cargar la lista de campos en una StringList y abordarlos desde el número de campos cargados.


procedure TForm1.Button1Click(Sender: TObject);
var
I,J,nCampos:Integer;
Sl:TstringList;

begin
sl:=Table1.FieldDefList;
nCampos:=sl.Count -1;
for i := 0 to nCampos do
begin
ShowMessage(Table1.FieldDefList[i].Name);
//showMessage(DataSource1.DataSet.FieldDefs.Items[i].FieldClass.ClassName );
//ShowMessage(DataSource1.DataSet.FieldDefs.Items[i].Name);
if DataSource1.DataSet.FieldDefs.Items[i].Required then
begin
ShowMessage(DataSource1.DataSet.FieldDefs.Items[i].Name +'Requerido');
for j := 0 to ComponentCount - 1 do
begin
if Components[j].ClassNameIs('TDBEdit') then
begin
If DataSource1.DataSet.FieldDefs.Items[i].Name =(Components[j] as TDBEdit).DataField then
(Components[j] as TDBEdit).Color := clLime;
end;
end;
end;
end;

Un Saludo.

andres1569
27-05-2003, 17:32:03
Hola:

Otra solución para lo que plantea Mosorio en el primer mensaje es recorriendo los componentes, averiguar cuáles son DBAware y asignar la propiedad Color, si la tienen. Pare ello nos velamos de la unit TypInfo para averiguar si cierta propiedad existe y para asignarla en tal caso. Tengo un código que hace algo parecido. Adaptado a este caso sería lo siguiente:



uses TypInfo;

{$R *.DFM}

procedure TForm1.Button1Click(Sender: TObject);
const
ColorCampoRequerido = clYellow;
var
PropInfo : PPropInfo;
ADataSet : TDataSet;
AField : TField;
s : String;
i : Integer;
begin
for i:=0 to ComponentCount - 1 do
begin
// Primero comprobamos que el control es DBAware
PropInfo := GetPropInfo (Components[i].ClassInfo, 'DataSource');
if (PropInfo <> nil) AND (PropInfo^.PropType^.Kind = tkClass) then
begin
// Nos aseguramos que está realmente enlazado a un TDataset
ADataSet := TDataSource(GetOrdProp (Components[i], PropInfo)).DataSet;
if ADataSet <> nil then
begin
// Obtenemos el nombre del campo al que está ligado
PropInfo := GetPropInfo (Components[i].ClassInfo, 'DataField');
if (PropInfo <> nil) then
begin
// Obtenemos el campo al que está ligado y miramos si Required = TRUE
s := GetStrProp(Components[i], PropInfo);
AField := ADataSet.FindField (s);
if (AField <> nil) AND (AField.Required) then
begin
// Comprobamos si el control tiene una propiedad Color y la asignamos
PropInfo := GetPropInfo (Components[i].ClassInfo, 'Color');
if PropInfo <> nil then
SetOrdProp(Components[i], PropInfo, ColorCampoRequerido);
end;
end;
end;
end;
end;
end;



Un saludo

mosorio
29-05-2003, 23:21:00
Hola delphoros!
Agradesco toda la ayuda que me han dado, en especial a quellos que han aportado sus ideas. Andres ha funcionado perfectamente, claro que creo que la rutia es un poco larga, mirare si se puede optimizar más adelante.