PDA

Ver la Versión Completa : Problema de código


Mathom
18-11-2005, 13:36:10
Hola, este es el código de un botón "aceptar". Es un pequeño formulario donde hay 2 DBEdits, el tema es que quiero que si los dos han sido rellenados inserte el nuevo registro pero si uno de los dos está vacio aparezca un mensaje de advertencia pero sin grabar el dato que si que está. Utilizo un "if" donde si los dos son "<>" de vacio inserte el registro pero cuando solo relleno uno no entre en el with y por lo tanto no grabe nada, sin embargo aunque sólo rellene uno de los dos me entra en el with modificando el registro. Os dejo el código a ver si veis el fallo, yo me he encabezonado y no lo veo...


procedure TForm2.BitBtn2Click(Sender: TObject);
begin
If ((DBEdit1.text <> '') and (DBEdit2.text <> '')) then
begin
With DataModule7.Table1 Do
Begin
Try
Insert;
Post;
Except
Application.MessageBox ('El nombre introducido no es correcto'+chr(13)+
'El nombre esta repetido, prueba con otro',
'Insertar registro',
Mb_Ok+Mb_IconStop);
Cancel;
Insert;
End;
End;
end
else
ShowMessage ('¡Debe rellenar todos los campos!')
end;

end.

aleee

vtdeleon
18-11-2005, 14:07:08
Saludos
Prueba con esto (trim())If ((trim(DBEdit1.text) <> '') and (trim(DBEdit2.text) <> '')) then

lucasarts_18
18-11-2005, 14:09:52
Hola:

Prueba así:


procedure TForm2.BitBtn2Click(Sender: TObject);
begin
If (DBEdit1.text <> '') and (DBEdit2.text <> '') then
begin
With DataModule7.Table1 Do
Begin
Try
Insert;
Post;
Except
Application.MessageBox ('El nombre introducido no es correcto'+chr(13)+
'El nombre esta repetido, prueba con otro',
'Insertar registro',
Mb_Ok+Mb_IconStop);
Cancel;
Insert;
End;
End;
end
else
ShowMessage ('¡Debe rellenar todos los campos!')
end;

end.

Tenías unos parentesis demás..:p

Mathom
18-11-2005, 17:50:33
Ante todo, gracias. La solción que me da LucasArt ya la he probado y no funciona correctamente (al menos como yo quería). Ahora probaré lo vtdeleon a ver que tal....;)

lucasarts_18
18-11-2005, 18:05:29
Hola.

Seguro debe ser un espacio que te queda en blanco, en ese sentido lo de VTDELEON debería funcionar, aún así yo te recomiendo que no uses de esa forma los parentesis, de hecho nunca he visto de esa forma la sentencia.

Hasta Luego -

Mathom
18-11-2005, 20:04:58
No es lo normal. Me refiero a utilzar así los parentesis, lo que pasa es que como no me funcionaba como yo esperaba he empezado a hacer pruebas por si era algo de los parentesis. Lo normal es que los ponga:

if (DBEdit1.text = ' ') and (DBEdit2.text = ' ' ) then

aún no he probado lo de trim. Tengo tres frentes abiertos ahora con la aplicación.. en cuanto lo pruebe os comento como he quedado.

gracias a los dos.

Mathom
18-11-2005, 20:11:41
Bien, he probado tanto el que me ha dicho vtdeleon
If ((trim(DBEdit1.text) <> '') and (trim(DBEdit2.text) <> '')) then ...como...

If((trim(DBEdit1.text) <> '') and (trim(DBEdit2.text) <> '') then ...el resultado sigue siendo el mismo..me sigue entrando dentro del with de todos modos...:(

roman
18-11-2005, 20:22:12
Para empezar, pon un punto de corte en la línea que sigue al condicional y examina el valor de DBEdit1.Text y DBEdit2.Text. Muy posiblemente observes que sí tienen algún dato.

Por otra parte te comento que lo que haces es muy, pero muy raro y da pie a pensar que el error viene de otro lado.

¿Qué hace un Insert dentro del with? Eso va a provocar que el registro actual, el que estás comparando con los DBEdits, se guarde en la base y se inserte uno más en blanco. El post que le sigue guardará entonces tal registro en blanco.

Si lo que quieres es validar que ambos campos estén llenos tienes dos opciones. Una es asignar el evento OnValidate a cada campo y verificar que no esté vacío. Esta a mi no me gusta porque impide que el usuario pueda moverse de campos hasta no llenar uno.

La otra opción es usar el evento BeforePost del Table asociado y ahí checar que los campos se hayan llenado.

// Saludos

maeyanes
18-11-2005, 20:24:13
Trata con:


if not DBEdit1.Field.IsNull and not DBEdit2.Field.IsNull then
begin
//...


otra forma podría ser:


if (DBEdit1.Field.AsString <> '') and (DBEdit2.Field.AsString <> '') then
begin
//...




Saludos...

lucasarts_18
18-11-2005, 20:31:53
otra forma podría ser:


if (DBEdit1.Field.AsString <> '') and (DBEdit2.Field.AsString <> '') then
begin
//...


Esta última tengo mis dudas, de esa forma pienso yo (no estoy seguro) que solo sirve cuando traes valores desde la base de datos, en este caso los datos se están ingresando por lo tanto que valor tendrá Field.asString ??

Hasta Luego -

roman
18-11-2005, 20:40:49
Quizá me equivoque pero pienso que ni Field.AsString ni Field.IsNull serán seguros.

Cuando se edita en un DBEdit, los cambios no se reflejan en el buffer del registro activo sino hasta que el foco se mueve a otro campo. Si el botón que se intenta usar es un SpeedButton que no gana el foco, o tiene el atributo deafult y el usuario oprime enter, quizá no se vacíen los datos en el buffer.

Por ello insisto, ésta no es la forma de atacar la validación de campos. Más aún, en la parte del except, no tiene sentido un Insert luego de un Cancel.

Me da la impresión de que el compañero Mathom tiene algunos conceptos poco claros y convendría que los repensara antes de lanzarse en la búsqueda de una solución en un código que de por sí está planteado de forma poco ortodoxa.

// Saludos

maeyanes
18-11-2005, 20:57:25
Esta última tengo mis dudas, de esa forma pienso yo (no estoy seguro) que solo sirve cuando traes valores desde la base de datos, en este caso los datos se están ingresando por lo tanto que valor tendrá Field.asString ??

Hasta Luego -

Como bien dice Roman:


Cuando se edita en un DBEdit, los cambios no se reflejan en el buffer del registro activo sino hasta que el foco se mueve a otro campo.


Ahora, viendo el código que puso Mathom al inicio, se deduce que el control que usa es un TBitButton, el cual si agarra el foco cuando se presiona en él.

También es cierto lo que comenta Roman, de que existen mejores formas de hacer estas comprobaciones, solo que yo intenté darle una solución basado en lo que estaba intentando hacer desde un principio.


Saludos...

Mathom
18-11-2005, 21:30:09
Desde luego, estoy muy verde. EL tema es que esa parte de código la cogí de una explicación que me hicieron unos compañeros por lo que la estaba aprovechando. Entonces vosotros eliminariais el insert y para validar utilizaríais el OnValidate en cada campo, no es así??

Os agradezco ante todo que me digais que voy por mal camino, a ver si voy cogiendome pq cuantas más cosas voy aprendiendo más verde veo que estoy.

roman
18-11-2005, 23:16:09
No se trata de eliminar el Insert y ver si funciona. Se trata, pienso, en detenerte un momento para examinar qué es lo que haces y lo que debes hacer.

Vamos a suponer que en tu caso tienes un formulario con dos DBEdit. Estos están enlazados a un DataSource que a su vez estará enlazado a un Table. En cada DBEdit tienes asignado el campo al que se conectan.

En principio esto es todo lo que debes saber de los DBEdit. Esto es, normalmente no hace falta, ni se recomienda, acceder directamente a los datos del DBEdit, o sea, no usar propiedades como DBEdit.Text. Esto es así porque los controles enlazados a datos son meramente un intermediario entre el usuario y la tabla. Los datos que presentan son reflejo fiel de lo que contenga el registro activo y cualquier modificación que haga el usuario se transfiere automáticamente a la tabla.

Todas las operaciones se hacen a través del dataset asociado (el Table en este caso), los objetos TField del dataset, y sus eventos.

Cuando abres tu formulario, muy posiblemente tendrás un botón para agregar un nuevo registro con la instrucción:

Table.Append;

Esto inserta un registro en blanco y deja a tus DBEdit listos para comenzar a escribir sobre ellos sin hacer más nada. Pero observa, debes comenzar con el Append (o Insert, el que gustes), no se trata de una instrucción que se haga después de escribir los datos.

Como todos los datos son guardados en un buffer temporal, debes explícitamente indicar que queires grabar los datos con:

Table.Post;

que tendrías en otro botón.

Hasta aquí todo claro, sólo un par de líneas, una en el evento OnClick de cada botón.

Viene entonces el asunto de las validaciones. En tu caso debes asegurarte que ninguno de los dos campos esté vacío.

Lo que tú estás haciendo ahora, es hacer la validación en el botón que tienes, supongo, para guardar los datos. Pero este es el lugar incorrecto. ¿Por qué? Pues imagina que posteriormente debes manejar la misma tabla desde otro formulario distinto. Ahí tendrás que repetir la validación con lo que ya desperdiciaste código. Además, si en algún momento cambian las reglas de validación, tendrás que hacer las modificaciones pertinentes en todos los puntos donde accedas a esa tabla.

El punto es: normalmente la validación es independiente de la forma en que se inserten los registros. No importa si usas dbedits o un dbgrid u otro control similar, la regla debe ser siempre la misma: los campos no pueden estar vacíos.

Por ello, enfatizo, no debes basar tus validaciones en los valores de controles específicos. Lo recomendable es centralizar estas validaciones.

Hay dos lugares muy propicios para hacer las validaciones.

Uno es el evento OnValidate del campo asociado. Para ello debes agregar los objetos TField al dataset dando doble click sobre la componente (el Table) y escogiendo la opción "Select all fields" del menú contextual. O puedes agregar sólo los que requieras ver en tu aplicación. Cuando seleccionas uno de los campos, el inspector de objetos te mostrará las propiedades y eventos específicos para dicho objeto. Ahí encontrarás el evento OnValidate.

Ahora bien. Es cuestión de gustos, pero a mi no me acomoda esta forma de validar ya que el evento OnValidate se lanzará cada vez que el usuario intente mover el foco a otro campo, lo cual le impide navegar libremente por el formulario hasta estar satisfecho con lo escrito. En mi opinión esto era más de los tiempos de Clipper y sistemas en MS-DOS.

Otro punto donde puedes centralizar las validaciones, es en el evento BeforePost del dataset (el Table). Este evento se generará justo antes de que el registro se guarde en la tabla física, sin importar por qué medios se haga. Puede ser porque explíctamente usaste Table.Post o bien porque estabas en un DBGrid y moviste la selección a otro registro.

El evento BeforePost pasa como parámetro el DataSet que se está validando. En este momento ya puedes hacer uso de los valores de los campos:

DataSet.FieldByName('campo1').AsString

por ejemplo.

Si la validación no se cumple, usas abort para cancelar los cambios o

raise Exception.Create('mensaje aclarativo');

para indicar al usuario que hubo un problema y además cancelar los cambios.

Si observas, la importancia de esto (tanto OnValidate como BeforePost) es que en ningún momento haces referencia a un control en particular y por tanto, la parte medular de tu aplicación, como las validaciones, no dependen de los elementos que uses para la interfaz de usuario, de manera que puedes alterar ésta sin afectar lo importante.

Así pues, como ves, no se trata de eliminar el Insert, yo eliminaría todo el código del botón, por drástico que suene.

Y una recomendación. Si bien se puede aprender del código de otros, es importante que leas, antes de ponerte a teclear. Un buen lugar para empezar es el libro la Cara oculta de Delphi 4 de Ian Marteens, que podrás bajar gratuitamente de su sitio (http://www.marteens.com). Que no te mosquee la versión. Para los conceptos básicos te será igualmente bueno si usas un Delphi posterior.

Te aseguro que con una semana que leas la parte dedicada al acceso a datos, serás tú el que esté dando explicaciones a tus compañeros.

// Saludos

Lepe
18-11-2005, 23:48:04
De mayor quiero ser como roman ;)

PD: roman, has hecho caso omiso a tu firma... pero no te lo tendremos en cuenta esta vez.

lucasarts_18
19-11-2005, 00:46:01
De mayor quiero ser como roman ;)

mmmmm....mejor me voy a dormir que me dió sueño.
Quizás mañana aprenda de verdad, claro después de un buen sueño :D

Hasta Luego -

Mathom
19-11-2005, 17:01:27
que puedo decir después de toda la expicación....muchas gracias a todos y en especial a Roman.:p

Ahora sólo me queda aplicar lo que me has dicho y leerme el sitio que me has aconsejado e intentarlo...ya os diré como voy quedando.