Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Principal > Conexión con bases de datos
Registrarse FAQ Miembros Calendario Guía de estilo Temas de Hoy

Conexión con bases de datos

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 07-04-2004
Telemaco Telemaco is offline
Miembro
 
Registrado: feb 2004
Posts: 50
Poder: 21
Telemaco Va por buen camino
actualizar tabla al calcular un campo autocalculado

Hola a todos

estoy trabajando con Delphi 7 y sqlserver 2000 y en mi aplicacion en la tabla de fichajes transformo una cadena como esta 08:00 a un valor numerico, y pretendo asignarselo a un campo de la bd de tipo entero, pero siempre me sale el mismo error:
"stack over flow"
y no se como hacer que me modifique la bd con el dato que quiero introducir, alguien podria ayudarme.

Gracias.
Responder Con Cita
  #2  
Antiguo 07-04-2004
Avatar de guillotmarc
guillotmarc guillotmarc is offline
Miembro
 
Registrado: may 2003
Ubicación: Huelva
Posts: 2.638
Poder: 24
guillotmarc Va por buen camino
Hola.

¿ Como transformas a valor numérico ?. Porqué yo no veo claro que valor numérico corresponde a la cadena '08:00'

Saludos.
__________________
Marc Guillot (Hi ha 10 tipus de persones, els que saben binari i els que no).
Responder Con Cita
  #3  
Antiguo 07-04-2004
Telemaco Telemaco is offline
Miembro
 
Registrado: feb 2004
Posts: 50
Poder: 21
Telemaco Va por buen camino
he hecho una funcion que transforma de una cadena los numero en valores numericos y desecha los caracteres.

Cita:
Empezado por guillotmarc
Hola.

¿ Como transformas a valor numérico ?. Porqué yo no veo claro que valor numérico corresponde a la cadena '08:00'

Saludos.
Responder Con Cita
  #4  
Antiguo 07-04-2004
Avatar de guillotmarc
guillotmarc guillotmarc is offline
Miembro
 
Registrado: may 2003
Ubicación: Huelva
Posts: 2.638
Poder: 24
guillotmarc Va por buen camino
El mensaje de error te indica que tienes un desbordamiento de pila. ¿ Esta función es recursiva ?.

Vas a tener que poner algo de código, de la función que falla, y de como intentas actualizar el campo.

Saludos.
__________________
Marc Guillot (Hi ha 10 tipus de persones, els que saben binari i els que no).
Responder Con Cita
  #5  
Antiguo 07-04-2004
Telemaco Telemaco is offline
Miembro
 
Registrado: feb 2004
Posts: 50
Poder: 21
Telemaco Va por buen camino
Hola GuillotMarc

este es el codigo del procedimiento CalcFields
var
manyana,tarde:boolean;
M1,M2,T1,T2:String;
op,hor,min:integer;

h1,h2:string;
ht : array [0..2] of char;
mt : array [0..5] of char;
x:STRING;

m,t:Tdatetime;
horas:string;
i:byte;
hh,mm:string;
hint,mint:integer;

begin
op:= strtoint(FCronos.TipoAccion.text);
case op of
1 : {Actualizo los campos autocalculados'}
begin
manyana:=false;
tarde:=false;
if Tfichajes.FieldByName('HoraEntM').AsString >'00:00:00'
then begin
M1:=TFichajes.FieldbyName('HoraEntM').AsString;
end
else begin
manyana:=true;
{ M1:='07:07:00';}
end;
if (TFichajes.FieldByName('HoraSalM').AsString) > '00:00:00'
then begin
M2:=Tfichajes.FieldByName('HoraSalM').Asstring;
end
else begin
manyana:=true;
{ M2:='13:33:00'}
end;
if TFichajes.FieldByName('HoraEntT').AsString > '00:00:00'
then begin
T1:=Tfichajes.fieldbyname('HoraEntT').AsString;
end
else begin
Tarde:=true;
end;
if TFichajes.FieldByName('HoraSalT').AsString > '00:00:00'
then begin
T2:=Tfichajes.fieldbyname('HoraSalT').AsString;
end
else begin
Tarde:=true;
end;

if not manyana
then h1:=timetostr(strtotime(M1)-strtotime(M2))
else begin
h1:='00:00:00';
manyana:=true;
end;
if not tarde
then h2:=timetostr(strtotime(T1)-strtotime(T2))
else begin
h2:='00:00:00';
tarde:=true;
end;

x:=timetostr((strtotime(h1)+strtotime(h2)));
if (not tarde) and (not manyana)
then begin
FFichaEmp.GEFichaje.Font.color := clnavy;


TFichajes.FieldByName('HTXT').AsString:=x;
mm:='';hh:='';
TFichajes.fieldbyname('Mayana').asstring:=h1;
TFichajes.fieldbyname('Tarde').asstring:=h2;

horas:=x;
for i:=1 to length(horas) do
begin
if Horas[i] <> ':'
then if i<3 then hh:=hh+Horas[i]
else if i>3 then
if i<6 then mm:=mm+Horas[i];
end;
hint:=strtoint(hh);
mint:=strtoint(mm);
TFichajes.Edit; { AL AÑADIR ESTA LINEA ME DA DESBORDAMIENTO}
TFichajes.FieldByName('Horas').AsInteger:= hint;
TFichajes.FieldByName('Minutos').AsInteger:=mint;

end
else begin
FFichaEmp.GEFichaje.Font.Color :=clred;
TFichajes.FieldByName('HTXT').AsString:=x;

mm:='';hh:='';
horas:=x;

for i:=1 to length(horas) do
begin
if Horas[i] <> ':'
then if i<3 then hh:=hh+Horas[i]
else if i>3 then
if i<6 then mm:=mm+Horas[i];
end;
hint:=strtoint(hh);
mint:=strtoint(mm);
TFichajes.Edit;
TFichajes.FieldByName('Horas').AsInteger:= hint;
TFichajes.FieldByName('Minutos').AsInteger:=mint;

end;

Como ves el codigo es muy rudimentario, lo siento pero soy novato...jeje

gracias por tu ayuda.

Adios.

Cita:
Empezado por guillotmarc
El mensaje de error te indica que tienes un desbordamiento de pila. ¿ Esta función es recursiva ?.

Vas a tener que poner algo de código, de la función que falla, y de como intentas actualizar el campo.

Saludos.
Responder Con Cita
  #6  
Antiguo 07-04-2004
andres1569 andres1569 is offline
Miembro
 
Registrado: may 2003
Posts: 908
Poder: 22
andres1569 Va por buen camino
Hola, Telemaco, sería de agradecer que encerraras todo ese código entre etiquetas [ code ] y [ /code ], aparecería el código identado y más gente se animaría a investigarlo en busca de la solución ...

Un Saludo
__________________
Guía de Estilo
Responder Con Cita
  #7  
Antiguo 07-04-2004
Avatar de guillotmarc
guillotmarc guillotmarc is offline
Miembro
 
Registrado: may 2003
Ubicación: Huelva
Posts: 2.638
Poder: 24
guillotmarc Va por buen camino
Hola.

Un desbordamiento de pila, indica un bucle infinito de llamadas a procedimientos. ¿ El evento CalcFields que programas es sobre el mismo dataset TFichajes ?.

Probablemente la llamada al Edit, provoca que se vuelva a ejecutar el evento CalcFields, que vuelve a llamar al Edit, que vuelve a ejecutar el evento, ..., ..., ... Hasta el desbordamiento de pila.

¿ Para que necesitas llamar al Edit dentro del CalcFields ? Si los campos Horas y Minutos són campos Calculados, entonces no hace falta que llames al Edit, los puedes modificar tranquilamente. Si en lugar de ser campos calculados són campos normales, no deberías asignarles su valor en el CalcFields (que se ejecuta muchas veces por el mismo registro, y sin que hayan cambiado los valores de sus campos) sinó que tendrías que cambiar el valor, dentro del evento OnChange de los campos HoraEntM, HoraEntT, HoraSalM, HoraSalT, ...

Saludos.
__________________
Marc Guillot (Hi ha 10 tipus de persones, els que saben binari i els que no).
Responder Con Cita
  #8  
Antiguo 07-04-2004
Avatar de jachguate
jachguate jachguate is offline
Miembro
 
Registrado: may 2003
Ubicación: Guatemala
Posts: 6.254
Poder: 28
jachguate Va por buen camino
Dado que no está indentado, se me hace realmente dificil leer el código, y no lo he hecho (seguí la recomendación de Andres al respecto). Sin embargo me parece que, dado que se trata de un evento OnCalcFields, seguramente estas haciendo una asignación a un campo no calculado dentro del evento, con lo que éste se dispara nuevamente... provocando una recursividad indirecta, e infinita (ya que no hay condición que pare esta recursividad).

Esto lo podes comprobar fácilmente poniendo un breakpoint al inicio del método, siguiendolo paso a paso, y viendo como, al hacer alguna asignación (o probablemente la llamada a otra rutina que hace una asignación) el evento se dispara nuevamente (pasando por el breakpoint).

Yo elimino normalmente este efecto teniendo un flag en el formulario o módulo de datos, digamos FCalculando... que inicializas a false, y luego hago algo como esto en el evento:

Código:
Procedure Form1Table1CalcFields(parametros);

Begin
  if not FCalculando Then
  Begin
    FCalculando := True;
    // se enciende el flag, para evitar la recursividad indirecta.
    try  
      CodigoNormalDelEvento;
    finally
      FCalculando := False; // esto siempre se ejecuta, aunque el evento se aborte
      // por una condición de error.
    End;
  End;
  // de esta forma, no se ejecuta ni una sola línea si ya se ha entrado al evento 
  // una vez
End;
Hasta luego.

__________________
Juan Antonio Castillo Hernández (jachguate)
Guía de Estilo | Etiqueta CODE | Búsca antes de preguntar | blog de jachguate
Responder Con Cita
  #9  
Antiguo 08-04-2004
Telemaco Telemaco is offline
Miembro
 
Registrado: feb 2004
Posts: 50
Poder: 21
Telemaco Va por buen camino
Hola a todos de nuevo y disculparme pero no sabia que debia utilizar al etiqueta Code, aqui os paso de nuevo el codigo.

Código:
   var
     manyana,tarde:boolean;
     M1,M2,T1,T2:String;
      op,hor,min:integer;
   
      h1,h2:string;
      ht : array [0..2] of char;
      mt : array [0..5] of char;
      x:STRING;
   
      m,t:Tdatetime;
      horas:string;
      i:byte;
      hh,mm:string;
      hint,mint:integer;
   
   begin
    op:= strtoint(FCronos.TipoAccion.text);
    case op of
     1 : {Actualizo los campos autocalculados'}
           begin
             manyana:=false;
             tarde:=false;
              if Tfichajes.FieldByName('HoraEntM').AsString >'00:00:00'
                 then  begin
                         M1:=TFichajes.FieldbyName('HoraEntM').AsString;
                       end
                 else  begin
                        manyana:=true;
                        {    M1:='07:07:00';}
                       end;
              if (TFichajes.FieldByName('HoraSalM').AsString) > '00:00:00'
                 then  begin
                        M2:=Tfichajes.FieldByName('HoraSalM').Asstring;
                       end
                 else  begin
                        manyana:=true;
                       {  M2:='13:33:00'}
                       end;
              if TFichajes.FieldByName('HoraEntT').AsString > '00:00:00'
                 then begin
                       T1:=Tfichajes.fieldbyname('HoraEntT').AsString;
                       end
                 else  begin
                        Tarde:=true;
                         end;
              if TFichajes.FieldByName('HoraSalT').AsString > '00:00:00'
                 then  begin
                          T2:=Tfichajes.fieldbyname('HoraSalT').AsString;
                       end
                 else  begin
                        Tarde:=true;
                       end;
   
             if not manyana
                 then h1:=timetostr(strtotime(M1)-strtotime(M2))
                 else  begin
                        h1:='00:00:00';
                        manyana:=true;
                       end;
             if not tarde
                 then h2:=timetostr(strtotime(T1)-strtotime(T2))
                 else  begin
                         h2:='00:00:00';
                         tarde:=true;
                       end;
   
             x:=timetostr((strtotime(h1)+strtotime(h2)));
             if (not tarde) and (not manyana)
                 then  begin
                       FFichaEmp.GEFichaje.Font.color := clnavy;
   
   
                       TFichajes.FieldByName('HTXT').AsString:=x;
                       mm:='';hh:='';
                       TFichajes.fieldbyname('Mayana').asstring:=h1;
                       TFichajes.fieldbyname('Tarde').asstring:=h2;
   
                       horas:=x;
                       for i:=1 to length(horas) do
                         begin
                              if Horas[i] <> ':'
                                 then if i<3 then hh:=hh+Horas[i]
                                         else if i>3 then
                                     if i<6 then mm:=mm+Horas[i];
                         end;
                       hint:=strtoint(hh);
                       mint:=strtoint(mm);
                       TFichajes.Edit;   { AL AÑADIR ESTA LINEA ME DA DESBORDAMIENTO}
                       TFichajes.FieldByName('Horas').AsInteger:= hint;
                       TFichajes.FieldByName('Minutos').AsInteger:=mint;
   
                       end
                 else begin
                       FFichaEmp.GEFichaje.Font.Color :=clred;
                       TFichajes.FieldByName('HTXT').AsString:=x;
   
                       mm:='';hh:='';
                       horas:=x;
   
                       for i:=1 to length(horas) do
                         begin
                              if Horas[i] <> ':'
                                 then if i<3 then hh:=hh+Horas[i]
                                         else if i>3 then
                                     if i<6 then mm:=mm+Horas[i];
                         end;
                       hint:=strtoint(hh);
                       mint:=strtoint(mm);
                       TFichajes.Edit;
                       TFichajes.FieldByName('Horas').AsInteger:= hint;
                       TFichajes.FieldByName('Minutos').AsInteger:=mint;
   
                      end;
He probado tambien a utilizar el OnChange pero no termina de funcionarme bien, ya que no actua en todos los casos, sabriais decirme por que ocurre esto? os adjunto el codigo

Código:
 procedure TDM1.TFichajesHoraSalMChange(Sender: TField);
 var
 
    manyana,tarde:boolean;
    M1,M2,T1,T2:String;
    op,hor,min:integer;
 
    h1,h2:string;
    ht : array [0..2] of char;
    mt : array [0..5] of char;
    x:STRING;
 
    m,t:Tdatetime;
    horas:string;
    i:byte;
    hh,mm:string;
    hint,mint:integer;
 
 begin
    manyana:=false;
 
    if dm1.Tfichajes.FieldByName('HoraEntM').AsString >'00:00:00'
 	 then M1:=dm1.TFichajes.FieldbyName('HoraEntM').AsString
 	 else  manyana:=true;
    if (dm1.TFichajes.FieldByName('HoraSalM').AsString) > '00:00:00'
 	 then M2:=dm1.Tfichajes.FieldByName('HoraSalM').Asstring
 	 else manyana:=true;
    if not manyana
 		then h1:=timetostr(strtotime(M1)-strtotime(M2))
 		else  begin
 			   h1:='00:00:00';
 			   manyana:=true;
 			 end;
 	  x:=timetostr(strtotime(h1));
 	  if (not manyana)
 		  then  begin
 			   mm:='';hh:='';
 			   DM1.TFichajes.Edit;
 			   DM1.TFichajes.fieldbyname('Mayana').asstring:=h1;
 			   horas:=x;
 			   for i:=1 to length(horas) do
 				begin
 				   if Horas[i] <> ':'
 					  then if i<3
 						 then hh:=hh+Horas[i]
 						 else if i>3 then
 				   if i<6 then mm:=mm+Horas[i];
 				end;
 			   hint:=strtoint(hh);
 			   mint:=strtoint(mm);
 
 			   dm1.TFichajes.FieldByName('Horas').AsInteger:= hint;
 			   dm1.TFichajes.FieldByName('Minutos').AsInteger:=mint;
 			   end;
 
    dm1.TFichajes.Post;
    dm1.TFichajes.next;
 
 end;
Se dispara el evento en el momento que actualizo o modifico un valor del field HSalM. Al escribir este evento he eliminado el codigo que asiganba valores en el evento OnCalcFields, pero ahora tambien me aparece el "Stack Overflow" , alguna sugerencia???

Gracias a todos.
Responder Con Cita
  #10  
Antiguo 08-04-2004
__cadetill __cadetill is offline
Miembro
 
Registrado: may 2003
Posts: 3.387
Poder: 25
__cadetill Va por buen camino
Cita:
Empezado por Telemaco
Código:
TFichajes.Edit;   { AL AÑADIR ESTA LINEA ME DA DESBORDAMIENTO}
Es que el evento OnCalcFields no es para modificar los campos físicos de la tabla, sino SOLO los calculados. Al hacer un Edit (y luego un Post aunque sea implícito), es cuendo vuelve a saltar el evento OnCalcFields y, así, hasta el infinito y más allá

Si esos campos son los calculados, no hace falta que hagas el Edit, sencillamnete asignas los valores y listo
Responder Con Cita
  #11  
Antiguo 08-04-2004
Telemaco Telemaco is offline
Miembro
 
Registrado: feb 2004
Posts: 50
Poder: 21
Telemaco Va por buen camino
Ok, Gracias, lo he probado y va perfecto, pero ahora el problema es que me da desbordamiento en el evento OnChange, al hacer un Edit, el codigo del evento esta en mi anterior cita...(por no volverlo a poner )

si me puedes aportar alguna idea....gracias.

Cita:
Empezado por cadetill
Es que el evento OnCalcFields no es para modificar los campos físicos de la tabla, sino SOLO los calculados. Al hacer un Edit (y luego un Post aunque sea implícito), es cuendo vuelve a saltar el evento OnCalcFields y, así, hasta el infinito y más allá

Si esos campos son los calculados, no hace falta que hagas el Edit, sencillamnete asignas los valores y listo
Responder Con Cita
  #12  
Antiguo 08-04-2004
__cadetill __cadetill is offline
Miembro
 
Registrado: may 2003
Posts: 3.387
Poder: 25
__cadetill Va por buen camino
Cita:
Empezado por Telemaco
Ok, Gracias, lo he probado y va perfecto, pero ahora el problema es que me da desbordamiento en el evento OnChange, al hacer un Edit, el codigo del evento esta en mi anterior cita...(por no volverlo a poner )

si me puedes aportar alguna idea....gracias.
Si los campos que se modifican en el OnChange del DbEdit son calculados, repito lo que te decía anteriormente, el único lugar para asignar valores a los campos calculados es el OnCalcFields

Si son físicos y estás modificando el valor del campo que se visualiza en él, esto hará saltar el evento onChange de forma recursiva

Te aconsejo que pongas un punto de ruptura y lo debugees, yo no veo demasiado claro por donde biene el error
Responder Con Cita
  #13  
Antiguo 08-04-2004
Avatar de marto
marto marto is offline
Miembro
 
Registrado: may 2003
Ubicación: Barcelona, Catalunya
Posts: 882
Poder: 22
marto Va por buen camino
Cita:
Empezado por Telemaco
pero ahora el problema es que me da desbordamiento en el evento OnChange, al hacer un Edit,
Digo yo... ¿Si estás en el evento OnChange, no estás ya en edición? ¿Para qué necesitas hacer un Edit?
__________________
E pur si muove
Responder Con Cita
  #14  
Antiguo 08-04-2004
Avatar de guillotmarc
guillotmarc guillotmarc is offline
Miembro
 
Registrado: may 2003
Ubicación: Huelva
Posts: 2.638
Poder: 24
guillotmarc Va por buen camino
Hola.

A mi me parece que ya tienes todos los datos para solucionar el problema por ti mismo. Ya te hemos indicado que el problema de desbordamiento de pila se debe a un bucle infinto de disparos de eventos. Te hemos ayudado sobre que evento es más conveniente utilizar para cada caso. Y finalmente Jachguate te ha indicado como evitar los bucles infinitos en el caso de eventos que ejecutan código que forzosamente provoca que se vuelva a disparar el mismo evento.

Ahora lo tienes que solucionar tu, depurando el código para ver cual es la linea que provoca el desbordamiento, y poniendo puntos de ruptura en los eventos, para ver cual es el que se dispara infinitamente. Una vez detectado eso, tienes que solucionarlo, viendo si es que no estás realizando acciones necesarias, y protegiendo con un flag el evento que se dispara infiinitamente.

¿ Supongo que no estás esperando a que te pongamos nosotros el código de los eventos ?

Saludos.
__________________
Marc Guillot (Hi ha 10 tipus de persones, els que saben binari i els que no).
Responder Con Cita
  #15  
Antiguo 08-04-2004
Telemaco Telemaco is offline
Miembro
 
Registrado: feb 2004
Posts: 50
Poder: 21
Telemaco Va por buen camino
Por supuesto que no espero que me escribais el codigo, de hecho me habeis dado mas información de la que imaginaba que iba a tener, ahora solo me queda mirarmelo.

Os agradezco vuestra ayuda.

Un saludo.

Adios.

Cita:
Empezado por guillotmarc
Hola.

A mi me parece que ya tienes todos los datos para solucionar el problema por ti mismo. Ya te hemos indicado que el problema de desbordamiento de pila se debe a un bucle infinto de disparos de eventos. Te hemos ayudado sobre que evento es más conveniente utilizar para cada caso. Y finalmente Jachguate te ha indicado como evitar los bucles infinitos en el caso de eventos que ejecutan código que forzosamente provoca que se vuelva a disparar el mismo evento.

Ahora lo tienes que solucionar tu, depurando el código para ver cual es la linea que provoca el desbordamiento, y poniendo puntos de ruptura en los eventos, para ver cual es el que se dispara infinitamente. Una vez detectado eso, tienes que solucionarlo, viendo si es que no estás realizando acciones necesarias, y protegiendo con un flag el evento que se dispara infiinitamente.

¿ Supongo que no estás esperando a que te pongamos nosotros el código de los eventos ?

Saludos.
Responder Con Cita
Respuesta



Normas de Publicación
no Puedes crear nuevos temas
no Puedes responder a temas
no Puedes adjuntar archivos
no Puedes editar tus mensajes

El código vB está habilitado
Las caritas están habilitado
Código [IMG] está habilitado
Código HTML está deshabilitado
Saltar a Foro


La franja horaria es GMT +2. Ahora son las 13:42:18.


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
Copyright 1996-2007 Club Delphi