Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   OOP (https://www.clubdelphi.com/foros/forumdisplay.php?f=5)
-   -   Propiedad Locate (https://www.clubdelphi.com/foros/showthread.php?t=13913)

dsa132132 03-09-2004 12:42:48

Propiedad Locate
 
Hola a todos!

Necesito realizar unas comprobaciones en mi aplicación antes de eliminar un registro en la Base de Datos. El problema es que no se como realizar más de una comprobación, me explico;

if (not (DataModule.Query1.Locate('param1', Edit1.text, []))
and (DataModule.Query1.Locate('param2', edit2.text, []))
then Application.Messagebox ( ........

Si sólo realizo la comprobación de la primera línea todo va bien pero al hacer el AND el programa me salta las tres líneas de código como si no estuvieran ( Lo he probado podiendo un punto de ruptura y con F8). Por lo visto no lo estoy haciendo del modo correcto.

Alguna idea?

Gracias!!

Nuria 03-09-2004 13:24:56

Hola dsa!

Nunca se va cumplir la condición y por eso te salta las líneas.

Cuando haces un locate, te posicionas en el registro de la tabla, no puedes posicionarte en dos registros de la tabla a la vez por lo tanto nunca se cumple el if. Espero haberme explicado bien.

En vez de locate utiliza lookup o bien create una nueva consulta.

Espero que te sirva. Saludos!:)

dsa132132 03-09-2004 14:20:58

Hola!!

He probado con esto;

if (not (DataModule.Query1.Lookup('param1;param2', VarArrayOf(['edit1.text','edit2.text', [])))

Pero tanto con Lookup como con Locate me salen los mismos errores;
Missing operator or semicolon
Ordinal type required
Incompatible types: 'Integer' and 'String'

Por lo que he visto en la ayuda del Delphi lo podria hacer tambien con un Locate. Ahora ya no se qué hacer.

Muchas Gracias!!

marcoszorrilla 03-09-2004 14:24:03

Debieras de optar por la segunda opción que te indica Nuria, es decir crear una consulta con el predicado Or si obtienes algún registro haces lo que proceda.......


Un Saludo.

__cadetill 03-09-2004 14:41:05

El planteamiento de dsa132132 es totalmente correcto, lo que pasa es que quizás en lugar de AND ha de ser un OR (tampoco se exactamente lo que quiere conseguir), pero el uso de los 2 Locates en el IF no es erróneo

Código Delphi [-]
if (not (DataModule.Query1.Locate('param1', Edit1.text, [])) and //quizás OR???
   (DataModule.Query1.Locate('param2', edit2.text, [])) then 
  Application.Messagebox ( ........
Básicamente lo que hace el if este es que si no existe un registro en el que el campo "param1" sea igual a Edit1.Text (es decir, Param1 <> Edit1.Text) y existe un registro en el que el campo Param2 sea igual a Edit2.Text, muestre el mensaje

Quizás es que Param1 y Param2 no son los nombres de los campos??? Si fuera esto, tendrías que quitarle las comillas

No obstante, también creo que lo del SQL es una muy buena opción (por no decir la mejor si la tabla es grande)

Nuria 03-09-2004 14:54:07

Quizás no me explique bien, el uso de dos locates es correcto pero no el AND, porque nunca se cumplirá esa condición, no por otra cosa. Menos mal que siempre está cadetill para explicarlo mejor....;rolleyes:

marcoszorrilla 03-09-2004 15:24:27

El problema es que no nos dice que comprobación es la que quiere realizar. Yo por ejemplo para eliminar un cliente supongamos que la condición es que no tenga ninguna factura ni ningún albarán.

nContro:=0;

Busca Facturas.
Si encuentra 1, no interesa si tiene más ó no.
nContro:=nContro+1;

Busca Albaranes, lo mismo que el anterior.
nContro:=nContro+1;

Código Delphi [-]
if nContro > 0 then
ShowMessage('Imposible eliminar el cliente tiene albaranes o facturas activas.');

Un Saludo.

dsa132132 03-09-2004 15:48:02

Hola a todos;

Quizás he sido yo desde un principio el que no se ha explicado con claridad, lo que intento es lo siguiente;

Deseo eliminar en registro de la Base de Datos pero antes hago la comprobación de que ese registro existe en la Base de Datos. Hasta aqui bien.

Ese registro que deseo eliminar tiene 3campos como clave primaria (antes había puesto sólo 2 por simplificar mi consulta, supongo que será lo mismo), entonces intentava hacer un Locate sobre esos 3 campos porque si lo hago sobre uno solo no es correcto.

He probado con OR en vez de AND pero sigue saltándose la instrucción.

Muchas gracias a todos por vuestro interés!!

__cadetill 03-09-2004 15:49:47

Sí, vale, pero Busca Facturas y Busca Albaranes han de ser una función (por ejemplo) que realice o bien un Locate sobre las tablas pertienentes, o una sentencia SQL o lo que nos de la gana. Si la elección fuera la del Locate, se puede hacer todo directamente en el mismo IF y ahorrarnos la variable :p

De hecho, yo más o menos suelo hacer lo mismo que tu, pero en lugar de la variable, pongo un Exit
Código Delphi [-]
function TMiClase.BorraCliente(Codigo: integer): boolean
begin
  Result := false;

  if TieneFacturas(Codigo) then Exit;
  if TieneAlbaranes(Codigo) then Exit;
  ....
  Result := true;
end;
Como suelo hacer funciones, el que se encarga de mostrar o no el mensaje será el que llame a ésta.

No obstante, como ya decía anteriormente y comentas muy bien, sin saber exactamente lo que pretende conseguir con esos Locates, es hablar por hablar

__cadetill 03-09-2004 15:52:25

Vaya, antes respondo, antes se me adelanta :p

Si lo que quieres es mirar por 3 campos a la vez....

Código Delphi [-]
if MiTabla.Locate('campo1; campo2; campo3', VarArrayOf[Valor1, Valor2, Valor3], []) then
  Existe
else
  No Existe

jachguate 03-09-2004 16:00:25

Yo no veo ningún problema en usar dos locates en el mismo if, incluso con AND. Esto, porque delphi no se traga toda la comprobación de un bocado.

Realiza el primer locate, que deja el puntero en un registro, y luego el segundo, que lo deja en otro.

Ahora... que esto se vea como dos pasos en el debugger... eso no lo creo, pues la operación que traza es el IF, y no cada condición. Salvo que se pueda entrar a debugear el código del Locate, y que se trace con StepIn, entraria dos veces.

Otro punto a tener en cuenta es el estado de la directiva del compilador {$B} que es el Boolean ShortCircuit. Cuando está activado, que es mas optimo, hace que el compilador deje de evaluar las condiciones en cuanto pueda determinar el resultado de la operación completa. Asi, si está en {$B+}, y el primer Locate devuelve FALSE, nunca evaluará el segundo, pues no tiene sentido para el resultado de la operación, dado que se usa AND.

Si se usara OR y el primero devuelve TRUE, igual, nunca se evaluaria el segundo.

Si el programador necesita que se evaluen todas las condiciones, independientemente de esto, por ejemplo, porque realizan alguna tarea imprescindible, entonces debe desactivar el Short Circuit, bien dentro de la pestaña del compilador, para todo el proyecto, o bien con la directiva {$B-} en el punto donde le interese.

Saludos.

;)

jachguate 03-09-2004 16:07:34

Cita:

Empezado por dsa132132
Ese registro que deseo eliminar tiene 3campos como clave primaria (antes había puesto sólo 2 por simplificar mi consulta, supongo que será lo mismo), entonces intentava hacer un Locate sobre esos 3 campos porque si lo hago sobre uno solo no es correcto.

Viola!!!!

Este tampoco es correcto.

Supone que tenes los registros:

Código:

campo1  campo2  campo3
======  ======  ======
uno      uno      uno
dos      dos      dos
tres    tres    tres

y vos queres borrar el registro "uno-dos-tres", tu método actual (con and's o con or's) te devolverá verdadero, puesto que chequeas por separado que exista un registro con "uno", otro con "dos" y otro con "tres"... pero nunca que exista uno de la forma "uno-dos-tres".

Bien sea con un locate que abarque los tres campos, o con un Query que incluya los tres en el predicado, si podes garantizar que un registro existe en la BD.

Hasta luego.

;)

dsa132132 03-09-2004 17:25:39

Saludos!

Al final lo he hecho mediante IF anidados;

if (not (DataModule.Query1.Locate('param1', Edit1.text, []))
then Application.Messagebox ( 'Error......
else if (not (DataModule.Query1.Locate('param2', Edit1.text, []))
then Application.Messagebox (.....
...

No creo que sea la solución mas eficiente pero me ha parecido la más sencilla y he estado haciendo pruebas i parece que funciona bien.

Muchas gracias a todos por vuestra ayuda e interes!!

roman 03-09-2004 17:39:04

Cita:

Empezado por dsa132132
parece que funciona bien.

En efecto, parece, pero no funciona bien. Ha sido una casualidad que te resulte sólo por los datos específicos que tengas en tu tabla. Pero tarde o temprano surgirá una situación como la que te ejemplifica jachguate. Sinceramente no hay vuelta de hoja, basados en la descripción que das de lo que quieres hacer, tienes que hacer un sólo locate que abarque los tres campos.

// Saludos

__cadetill 03-09-2004 17:59:35

Cita:

Empezado por cadetill
Código Delphi [-]
if MiTabla.Locate('campo1; campo2; campo3', VarArrayOf[Valor1, Valor2, Valor3], []) then
  Existe
else
  No Existe

Cita:

Empezado por jachguate
Bien sea con un locate que abarque los tres campos, o con un Query que incluya los tres en el predicado, si podes garantizar que un registro existe en la BD.

:confused: :confused: :confused: :confused: Qué es lo que no has entendido de estas dos respuestas????

Cita:

Empezado por roman
Pero tarde o temprano surgirá una situación como la que te ejemplifica jachguate. Sinceramente no hay vuelta de hoja, basados en la descripción que das de lo que quieres hacer, tienes que hacer un sólo locate que abarque los tres campos.

A ver si a la tercera va la vencida :rolleyes: :rolleyes:

:D

kalimero 03-09-2004 18:15:12

Código:

if MiTabla.Locate('campo1; campo2; campo3', VarArrayOf[Valor1, Valor2, Valor3], []) then
Esta es la solucion mas 'pofesional' al tema. Como comenta Roman, el código que escribes solo funciona por casualidad. Probablemente en otra ocasion no funcione.

Saludos

Vales08 02-12-2011 14:52:13

Buen dia Foro..

Disculpa por meterme aca y no abrir un hilo nuevo, pero ya que estaba este problema planteado y al codigo lo saque de este hilo, me gustaria consultar una duda y un problema que tengo con tal codigo..
Yo estoy utilizando este codigo
Código Delphi [-]
if MiTabla.Locate('campo1; campo2; campo3', VarArrayOf[Valor1, Valor2, Valor3], []) then

pero el error que me salta ami es
Código:

[Error] Not enough actual parameters
yo lo interprete como que no hay suficientes parametros.. les paso mi codigo actual
Código Delphi [-]
...
var
  mes, anioo: Word;
  fecha: TDate;
  dia, mess: string;

begin
  case Meses.ItemIndex of
    1: mes:=1;
    2: mes:=2;
    3: mes:=3;
    4: mes:=4;
    5: mes:=5;
    6: mes:=6;
    7: mes:=7;
    8: mes:=8;
    9: mes:=9;
    10: mes:=10;
    11: mes:=11;
    12: mes:=12;
  end;
  case mes of
    1: mess:='ENERO';
    2: mess:='FEBRERO';
    3: mess:='MARZO';
    4: mess:='ABRIL';
    5: mess:='MAYO';
    6: mess:='JUNIO';
    7: mess:='JULIO';
    8: mess:='AGOSTO';
    9: mess:='SEPTIEMBRE';
    10: mess:='OCTUBRE';
    11: mess:='NOVIEMBRE';
    12: mess:='DICIEMBRE';
  end;
  case anio.ItemIndex of
    1: anioo:=2011;
    2: anioo:=2012;
    3: anioo:=2013;
    4: anioo:=2014;
    5: anioo:=2015;
    6: anioo:=2016;
    7: anioo:=2017;
    8: anioo:=2018;
    9: anioo:=2019;
    10: anioo:=2020;
  end;
  if not (DM.Q_agen_tur.Locate('MES; ANIO', VarArrayOf[mess, anioo], []))then
...

Me podrian decir donde o que estoy haciendo mal.. Desde ya muchisimas gracias..

ecfisa 02-12-2011 15:40:43

Hola Vales.

Cita:

Yo estoy utilizando este codigo

Código Delphi [-]
if MiTabla.Locate('campo1; campo2; campo3', VarArrayOf[Valor1, Valor2, Valor3], []) then

La sintáxis correcta es:
Código Delphi [-]
   Locate('Campo1; Campo2;...', VarArrayOf ( [Valor1, Valor2, ...] ), [])

Por favor recordá que : nueva pregunta = nuevo hilo ;)

Saludos.

jachguate 02-12-2011 17:48:27

Buen día.

Además de lo ya dicho por ecfisa, añadiría que tu código puede mejorar de varias maneras. Por ejemplo, mirá este código equivalente (pero más compacto):

Código Delphi [-]
...
var
  Año: Word;
  Mes: string;
const
  NombreMes: array[1..12] of string = ('ENERO', 'FEBRERO', 'MARZO', 'ABRIL', 'MAYO'
    , 'JUNIO', 'JULIO', 'AGOSTO', 'SEPTIEMBRE', 'OCTUBRE', 'NOVIEMBRE', 'DICIEMBRE');

begin
  //cuidado, el primer elemento del ComboBox (parece ser eso) tiene index 0, quizas haya que 
  //correr el arreglo, pero lo dejo así para que sea equivalente con el código publicado originalmente
  Mes := NombreMes[Meses.ItemIndex];
  Año := Anio.ItemIndex + 2010;
  if not DM.Q_agen_tur.Locate('MES; ANIO', VarArrayOf([Mes, Año]), []) then
...

Un saludo.

Cita:

Empezado por Vales08 (Mensaje 420261)
Disculpa por meterme aca y no abrir un hilo nuevo, pero ya que estaba este problema planteado y al codigo lo saque de este hilo, me gustaria consultar una duda y un problema que tengo con tal codigo..

Con respecto de esto, en este caso particular yo no veo problema en que no se abra un hilo nuevo, de hecho, creo que es mejor hacer tu consulta aquí para estar en contexto de lo ya dicho antes.

Un saludo.

Vales08 02-12-2011 21:54:41

Muchas gracias por sus respuestas, me comi los parentesis, aunque en verdad yo como no sabia la sintaxis me guie de la que habian expuesto y no sabia que los llevaba a tales parentesis, ahora me funciona barbaro..

Y con respecto al mejoramiento del codigo te lo agradezco jachguate, lo tendré en cuenta, aunque asi me funciona muy bien y estoy apunto de terminar este proyecto para ser entregado y rendir la tesis. si fuera en otra ocasion me tomaria el tiempo para hacerlo..

Muchas gracias por su tiempo, me fueron de gran ayuda..


La franja horaria es GMT +2. Ahora son las 01:13:49.

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