![]() |
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. |
Hola.
¿ Como transformas a valor numérico ?. Porqué yo no veo claro que valor numérico corresponde a la cadena '08:00' Saludos. |
he hecho una funcion que transforma de una cadena los numero en valores numericos y desecha los caracteres.
Cita:
|
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. |
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:
|
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 |
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. |
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); ;) |
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 Código:
procedure TDM1.TFichajesHoraSalMChange(Sender: TField); Gracias a todos. |
Cita:
Si esos campos son los calculados, no hace falta que hagas el Edit, sencillamnete asignas los valores y listo ;) |
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:
|
Cita:
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 :( |
Cita:
|
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. |
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:
|
La franja horaria es GMT +2. Ahora son las 17:21:03. |
Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi