PDA

Ver la Versión Completa : Cambio de valor de un campo en un grid


jafera
19-08-2010, 17:33:54
Hola de nuevo a todos.

Aprovechando vuestro "savoir faire" que dirian los franceses, os planteo otra duda que me ha surgido al trabajar con un JVDBGrid.

Tal y como comenté en mi anterior post, estoy trabajando con un grid que se llena mediante una tabla, todo esto en firebird 1.5.

Los datos de este grid son filtrados por un id del maestro, lógico claro, en los registros de este grid solo puede haber uno con un campo que se llama ACTUAL y que contenga el valor "S", este valor siempre es el último del grid.

Cuando añado un nuevo registro automaticamente le pone valor S al campo ACTUAL (onnewrecord), pero en el evento beforepost tengo puesto lo siguiente:


If Camions_Aux.State in [dsInsert] then
begin
Actual_S.Close;
Actual_S.ParamByName('ID_CAMIO').AsInteger := F_ModulDades.Camions_AuxID_CAMIO.Value;
Actual_S.ParamByName('ID').AsInteger:=F_ModulDades.Camions_AuxID.Value;
Actual_S.Open;
if Actual_S.RecordCount > 0 then
begin
ShowMessage('Només es pot asignar el camió a un parc');
Camions_AuxACTUAL.Value := 'N';
end;
end;


El motivo del state es para que no actue si estoy modificando un dato que no sea ACTUAL.

Bueno despues de soltar el lastre mi pregunta.

Puedo poner ACTUAL a S pero en el registro anterior al nuevo?, tal y como tengo el código actualmente me pone a S el ultimo registro y yo quisiera poner a S el penultimo.

Gracias a todos y saludos

Josep

ecfisa
19-08-2010, 19:15:41
Hola.

No me queda bién en claro si la 'S' la guardás en el maestro o el detalle, pero suponiendo que sea
sobre la tabla detalle, podrías hacer:


procedure TForm1.IBDataSetDetalleAfterPost(DataSet: TDataSet);
begin
with IBDataSetDetalle do
begin
Prior; // ir al anterior
Edit; // modo edición
FieldByName('Campo_a_ponerle_la_S').AsString:= 'S';
Post; // guardar
end;
end;


Saludos.

jafera
19-08-2010, 19:50:53
Buenas ecfisa, a ver si lo he entendidobien, yo coloco el codigo aqui, lo he insertado en el código que ya tenia yo puesto en el evento


procedure TF_ModulDades.Camions_AuxAfterPost(DataSet: TDataSet);
var Pos:TBookmark;
begin
Pos := Camions_Aux.GetBookmark;
IBTBombers.CommitRetaining;
Camions_Aux.Close;
Camions_Aux.Open;
Camions_Aux.GotoBookmark(Pos);
with Camions_Aux do
begin
Prior;
Edit;
Camions_AuxACTUAL.Value:= 'N';
Post;
end;
Camions_Aux.FreeBookmark(Pos);
end;


El resultado es que hace el cambio a "N" pero entra en un bucle sin fin que tengo que cancelar

Que es lo que hago mal?

En el before post tengo esto


procedure TF_ModulDades.Camions_AuxBeforePost(DataSet: TDataSet);
begin
If Camions_Aux.State in [dsInsert] then
begin
Actual_S.Close;
Actual_S.ParamByName('ID_CAMIO').AsInteger := F_ModulDades.Camions_AuxID_CAMIO.Value;
Actual_S.ParamByName('ID').AsInteger:=F_ModulDades.Camions_AuxID.Value;
Actual_S.Open;
if Actual_S.RecordCount > 0 then
begin
ShowMessage('Només es pot asignar el camió a un parc');

//Camions_AuxACTUAL.Value := 'N';
end;
end;
end;


Gracias

Josep

ecfisa
19-08-2010, 20:02:05
Hola.

No sé si será esto pero fijate el comentario sobre esta parte de tu código:


procedure TF_ModulDades.Camions_AuxAfterPost(DataSet: TDataSet);
var Pos:TBookmark;
begin
Pos := Camions_Aux.GetBookmark;
IBTBombers.CommitRetaining;
Camions_Aux.Close;
Camions_Aux.Open;
Camions_Aux.GotoBookmark(Pos);
with Camions_Aux do
begin
Prior; // Un registro hacia atrás
Edit;
Camions_AuxACTUAL.Value:= 'N'; // Ahora estamos en el anteúltimo, no iba 'S' ?
Post;
end;
Camions_Aux.FreeBookmark(Pos);
end;


Según te había entendido querías que el anteúltimo tuviera la letra 'S'.
Los bookmarks los podés evitar si despues de post hacés Next, retrocedemos un paso con Prior y volvemos a darlo con Next.


procedure TF_ModulDades.Camions_AuxAfterPost(DataSet: TDataSet);
begin
with Camions_Aux do
begin
Close;
Open;
Prior; // Un registro hacia atrás
Edit;
Camions_AuxACTUAL.Value:= 'S';
Post;
Next; // Volvemos al inicial
end;
end;


Saludos.

jafera
19-08-2010, 20:06:34
Buenas de nuevo, si puse "S" pero tiene que ser "N", "S" se quedará en el nuevo registro.

Yo no veo ninguna diferencia entre lo que he puesto yo en rojo y lo que me dices tu, igual me pierdo.

Saludos

Josep

ecfisa
19-08-2010, 20:17:32
Probaste sacando los Bookmark ?

Saludos.

ecfisa
19-08-2010, 20:36:14
Perdón jafera :o, a primera vista parecía que funcionaría, pero no es así.

Hice la prueba y se produce el ciclo infinito.

Es lógico por que el Post dentro del AfterPost dispara otro evento AfterPost y vuelve al evento y dispara otro y otro... :)


Es decir que vas a tener que buscar otra forma para la realizar la actualización.

¿ No podés hacer el cambio secuencialmente antes o después de guardar el nuevo registro ?



Saludos.

coso
19-08-2010, 20:54:04
Hola, una manera poco elegante seria desactivando el AfterPost y al final volverlo a activar :


procedure TForm1.IBDataSetDetalleAfterPost(DataSet: TDataSet);
begin
IBDataSetDetalle.AfterPost := nil;

with IBDataSetDetalle do
begin
Prior; // ir al anterior
Edit; // modo edición
FieldByName('Campo_a_ponerle_la_S').AsString:= 'S';
Post; // guardar
end;

IBDataSetDetalle.AfterPost := IBDataSetDetalleAfterPost;
end;


de todas maneras, creo que estudiandolo con detalle podrias sacar una solucion mas correcta, sin tener que usar los dos eventos del Beforepost y del AfterPost. Saludos

ecfisa
19-08-2010, 20:59:44
Hola de nuevo.

Estube probando y lo solucione así:


procedure TF_ModulDades.Camions_AuxAfterPost(DataSet: TDataSet);
begin
TF_ModulDades.AfterPost:= nil; // AfterPost desactivado.
with Camions_Aux do
begin
Close;
Open;
Prior;
Edit;
Camions_AuxACTUAL.Value:= 'N';
Post;
Next;
end;
TF_ModulDades.AfterPost:=Camions_AuxAfterPost; // AfterPost activado
end;


Saludos.

ecfisa
19-08-2010, 21:04:05
Se me adelantó el amigo coso...:D:D

Pd.: Me alegra por que entonces no era tan mala la idea :)

Saludos.

cloayza
20-08-2010, 14:33:44
Yo lo haria asi...

{Antes de Insertar un nuevo registro me voy al ultimo
y cambio su estado a 'N'}
procedure TForm1.Camions_AuxBeforeInsert(DataSet: TDataSet);
begin
Camions_Aux.Last;
Camions_Aux.Edit;
Camions_AuxACTUAL.Value:= 'N';
Camions_Aux.Post;
end;

{Si se cancelo la accion de insertar, restauro el valor del ultimo registro
a 'S'}
procedure TForm1.Camions_AuxAfterCancel(DataSet: TDataSet);
begin
{Esto solo se debe hacer cuando Dataset.State=dsInsert}
if DataSet.State <> dsInsert then Exit;

Camions_Aux.last;
Camions_Aux.Edit;
Camions_AuxACTUAL.Value:= 'S';
Camions_Aux.Post;
end;

{Para un nuevo registro le asigno el valor por defecto 'S'}
procedure TForm1.Camions_AuxNewRecord(DataSet: TDataSet);
begin
Camions_AuxACTUAL.Value:= 'S';
end;


Espero te sirva...

jafera
20-08-2010, 17:14:18
Gracias a todos de nuevo.

El último código de cloayza es el que mejor se me ha adaptado a mis necesidades, aunque he realizado ligeras variaciones de condicionado al borrar un registro o al modificarlo.

Saludos a todos

Josep

jafera
20-08-2010, 17:24:38
Una duda de nuevo al mismo problema.
Cuando intento insertar un nuevo registro me lanza un error de stack overflow supongo por el código siguiente


procedure TF_ModulDades.Camions_AuxBeforeInsert(DataSet: TDataSet);
begin
Camions_Aux.Last;
Camions_Aux.Edit;
Camions_AuxACTUAL.Value:= 'N';
Camions_Aux.Post;
end;


Codigo el cual no se puede ejecutar ya que el registro que estoy insertando es el primero y no hay last.

Como puedo controlarlo?

Gracias

Josep

jafera
20-08-2010, 17:34:47
Ya está, hoy vuelvo a tener el dia oscuro

If RecordCount > 0 then

Saludos

Josep

cloayza
23-08-2010, 00:24:12
Que bueno saber que lograste solucionar tu problema, efectivamente el error que indicas se produce, con la correccion que indicas salvas el problema...

Un abrazo.