Cada vez que el usuario termine de llenar (o cambiar) una terna, deberás comparar contra todas las demás para ver si está repetida. Eso de inmediato sugiere un ciclo en donde la terna se compara con cada una de las otras. Esto implica un múltiple recorrido de todos los controles. Para facilitar eso, yo declararía un arreglo de todos los Edits:
Código Delphi
[-]
type
TTerna = array[1..3] of TEdit;
var
Lineas: array[1..40] of TTerna;
E inicializaría el arreglo en el constructor del formulario:
Código Delphi
[-]
Lineas[1, 1] := Edit1A;
Lineas[1, 2] := Edit1B;
Lineas[1, 3] := Edit1C;
Lineas[2, 1] := Edit2A;
Lineas[2, 2] := Edit2B;
Lineas[2, 3] := Edit2C;
De esta forma evitas tener que referirte a los controles por su nombre. Esto puede ser costoso porque métodos como FindComponent lo que hacen de por sí es un ciclo por todos los componentes del formulario en busca de uno con el nombre dado. Esto, multiplicado por todas la veces que vas a tener que acceder al control para comparar podría ser un camino muy largo.
Para hacer la comparación, puedes implementar una función de comparación en un ciclo:
Código Delphi
[-]
function Coincide(Terna1, Terna2: TTerna): Boolean;
Result := (Terna1[1].Text = Terna2[1].Text) and (Terna1[2].Text = Terna2[2].Text) and (Terna1[3].Text = Terna2[3].Text);
end;
function Existe(Terna: TTerna): Boolean;
var
I: Integer;
begin
Result := false;
for I := 1 to 40 do
if Coincide(Terna, Lineas[i]) then
begin
Result := true;
break;
end;
end;
Esto lo escribo al vuelo así que puede estar incorrecto, pero es para dar la idea.
// Saludos