各位大哥,小弟现在在练习一个人事管理的MIS,程序有个统计正常工作时间,加班时间,出差、迟到、早退
的模块,其中统计有如下的代码
procedure TF_stat.B_statClick(Sender: TObject);
var
  MyInifile:Tinifile;
  Person_id:String;
  i,j,n,counter:integer;
  Time:Array [0..3] of TDateTime;
  Hour:Array [0..1] of Integer;
  StartTime,EndTime:TDate;
  TimeStamp,Late_Time,Early_Time,Work_start,Work_end:TDateTime;
  Late,Early,Absent,Leave,Errand:Boolean;
  WorkHour,OverHour,LeaveHDay,ErrandHDay:Integer;
  LateTimes,EarlyTimes,AbsentTimes:SmallInt;
  Temp:String;
begin
  MyInifile:=Tinifile.Create(ExtractFilePath(Paramstr(0))+'workplan.ini');
  Time[0]:=StrToTime(MyInifile.ReadString('WorkPlan','Time1','9:00:00'));
  Time[1]:=StrToTime(MyInifile.ReadString('WorkPlan','Time2','12:00:00'));
  Time[2]:=StrToTime(MyInifile.ReadString('WorkPlan','Time3','13:00:00'));
  Time[3]:=StrToTime(MyInifile.ReadString('WorkPlan','Time4','18:00:00'));
  Hour[0]:=Round((Time[1]-Time[0])*24);
  Hour[1]:=Round((Time[3]-Time[2])*24);
  StartTime:=StrToDate(i_start_time.Text);
  EndTime:=StrToDate(i_end_time.Text);
  with DM_main do
  begin
    //提取员工列表
    T_person.Filter:='STATE=''T''';
    T_person.Filtered:=True;
    T_person.Open;
    n:=T_person.RecordCount;
    i:=0;
    Gauge1.Progress:=0;
    T_person.First;
    while not T_person.Eof do
    begin
      //获取出勤记录
      Person_id:=T_person['ID'];
      Q_attend.Close;
      Q_attend.Params.ParamValues['PERSON']:=Person_id;
      Q_attend.Params.ParamValues['STARTTIME']:=StartTime;
      Q_attend.Params.ParamValues['ENDTIME']:=EndTime+1;
      Q_attend.Open;
      Q_attend.First;
      //初始化
      WorkHour:=0;
      OverHour:=0;
      LeaveHDay:=0;
      ErrandHDay:=0;
      LateTimes:=0;
      EarlyTimes:=0;
      AbsentTimes:=0;
      TimeStamp:=StartTime;
      while TimeStamp<EndTime+0.1 do
      begin
       if (DayOfWeek(TimeStamp)<>1) and (DayOfWeek(TimeStamp)<>7) then
       begin
        for j:=0 to 1 do //遍历班次
        begin
          Late_Time:=TimeStamp+Time[2*j];
          Early_Time:=TimeStamp+Time[2*j+1];
          //判断是否请假
          Q_leave.Close;
          Q_leave.Params.ParamValues['PERSON']:=Person_id;
          Q_leave.Params.ParamValues['STARTTIME']:=Late_Time;
          Q_leave.Params.ParamValues['ENDTIME']:=Early_Time;
          Q_leave.Open;
          Leave:=(Q_leave.RecordCount>0);
          //判断是否出差
          Q_errand.Close;
          Q_errand.Params.ParamValues['PERSON']:=Person_id;
          Q_errand.Params.ParamValues['STARTTIME']:=Late_Time;
          Q_errand.Params.ParamValues['ENDTIME']:=Early_Time;
          Q_errand.Open;
          errand:=(Q_leave.RecordCount>0);
          if leave then  //请假
            Inc(LeaveHDay)
          else if errand then   //出差
          begin
            Inc(ErrandHDay);
            WorkHour:=WorkHour+Hour[j];
          end
          else        //正常上班
          begin
            Work_start:=Late_Time;
            Work_end:=Early_Time;
            Late:=True;
            Absent:=False;
            //判断是否迟到
            while (not Q_attend.Eof) and (Q_attend['IO_TIME']<=Late_Time) do
            begin
              Late:=(Q_attend['IN_OUT']='O');
              Q_attend.Next;
            end;
            //判断是否旷工
            if Late then
            begin
              if (not Q_attend.Eof) and (Q_attend['IO_TIME']<Early_Time) then
                Work_start:=Q_attend['IO_TIME']  //记录迟到时间
              else
                Absent:=True;
            end;
            Early:=False;
            //判断是否早退
            while (not Q_attend.Eof) and (Q_attend['IO_TIME']<Early_Time) do
            begin
              Early:=(Q_attend['IN_OUT']='O');
              if Early then
                Work_end:=Q_attend['IO_TIME']
              else
                Work_end:=Early_Time;
              Q_attend.Next;
            end;
            if Absent then
              Inc(AbsentTimes)
            else
            begin
              if Late then
                Inc(LateTimes);
              if Early then
                Inc(EarlyTimes);
              WorkHour:=WorkHour+Round((Work_end-Work_start)*24); //计算实际工作时间
            end;
          end;//一个班次判断结束
        end; //下一班次
       end; //是否休息日
       TimeStamp:=TimeStamp+1;//推进一天
      end; //后一天考勤
      //统计加班时间
      Q_overtime.Close;
      Q_overtime.Params.ParamValues['PERSON']:=Person_id;
      Q_overtime.Params.ParamValues['STARTTIME']:=StartTime;
      Q_overtime.Params.ParamValues['ENDTIME']:=EndTime;
      Q_overtime.Open;
      try
        //overhour :=Q_overtime.fieldbyname('sumr').value;        OverHour:=Q_overtime['SUMR'];
      except
        OverHour:=0;
      end;
      //增加/修改考勤记录
      T_stat.Close;
      T_stat.Filter:='PERSON='''+Person_id+''' AND YEAR_MONTH='''+i_time.Text+'''';
      T_stat.Filtered:=True;
      T_stat.Open;
      if T_stat.RecordCount=0 then
      begin
        //获取计数
        T_counter.Filter:='ID=''S''';
        T_counter.Filtered:=True;
        T_counter.Open;
        counter:=T_counter['COUNTER_VALUE'];
        Inc(counter);
        T_counter.Edit;
        T_counter['COUNTER_VALUE']:=counter;
        T_counter.Post;
        T_counter.Close;
        T_stat.AppendRecord([counter,i_time.Text,Person_id,WorkHour,OverHour,LeaveHDay,ErrandHDay,LateTimes,EarlyTimes,AbsentTimes]);
      end
      else
      begin
        T_stat.Edit;
        T_stat['WORK_HOUR']:=WorkHour;
        T_stat['OVER_HOUR']:=OverHour;
        T_stat['LEAVE_HDAY']:=LeaveHDay;
        T_stat['ERRAND_HDAY']:=ErrandHDay;
        T_stat['LATE_TIMES']:=LateTimes;
        T_stat['EARLY_TIMES']:=EarlyTimes;
        T_stat['ABSENT_TIMES']:=AbsentTimes;
        T_stat.Post;
      end;
      Inc(i);
      Gauge1.Progress:=(100*i) div n;
      T_person.Next;
    end;  //下一个员工考勤
  end; //with
end;
其中变量overhour保存加班时间,Q_overtime的sql属性值为select sum(work_hours) as sumr from overtime
where person=:person and work_date>=:starttime and work_date<:endtime,表overtime的结构为
CREATE TABLE OVERTIME (ID INTEGER NOT NULL,
        PERSON CHAR(6) NOT NULL,
        WORK_HOURS SMALLINT NOT NULL,
        WORK_DATE datetime NOT NULL,
CONSTRAINT OVERTIME_ID PRIMARY KEY (ID))
    点击统计按钮,程序提示“invalid variant type conversion",代码窗下面提示
“[Hint] u_stat.pas(144): Value assigned to 'OverHour' never used”,144行为OverHour:=0;在OverHour:=Q_overtime['SUMR'];设置断点,鼠标移动到WorkHour,OverHour,LeaveHDay等上都会显示它的值,但移动到OverHour却没反应,
如果把OverHour:=Q_overtime['SUMR'];注释掉,则程序没有任何提示(此时统计的加班时间为0),
小弟苦苦思索却始终找不到错在哪里,各位前辈请指点啊!
小弟多谢了!!!

解决方案 »

  1.   

    设置断点进行跟踪,这里有使用了Variant类型的函数,你看一下在哪里,还有你的程序结构太乱了,为何不分为几个函数或模块呢?
      

  2.   

    在OverHour:=Q_overtime['SUMR'];出错
      

  3.   

    试试
    overhour :=Q_overtime.fieldbyname('sumr').AsInteger ;
      

  4.   

    那个[hint]只不过是编译器的警告而已,没什么作用。
    从错误的提示分析“非法的变量类型转换”的信息看,你的错误出在进行类型转换的时候。从你的程序看strtodate,strtotime疑点较大,所以在这些函数上设上断点就可以了。
    事实上,我查遍vcl的源码发现报这个错的函数就是时间转换函数。
      

  5.   

    谢谢各位前辈,特别是findcsdn,rainsea和wjlsmail。真是奇怪了,昨天晚上我在家里的电脑上运行那个程序,就没有提示;我把程序考到盘上带到单位的机器上运行,就出那个提示了。
        难道是数据库的问题?我今天把单位的数据库考到家里的电脑上再试试(不过也不应该啊,单位的overtime表只有4条记录,每条记录都非空啊)。
        TO  wjlsmail:
        你写的那个语句好用。但OverHour:=Q_overtime['SUMR'];在家里的电脑上也好用。
        TO  findcsdn:
        前辈,非常感谢你的答复,但我确实是太菜了,再麻烦问一下在strtodate,strtotime等处设置断点再怎样跟踪调试之类的。另外,在OverHour:=0;那行左边没有小菱形(点一下出来个小红圆里面是叉号而不是对号,右边的代码变成绿色而不是红色),在LeaveHDay:=0;设置断点后,当鼠标移动到前面的变量除了OverHour都能显出值来,惟独移到OverHour上什么也不反应,是不是OverHour有什么问题啊?
        小弟多谢了!!!
      

  6.   

    看到哪个[hint]了吗?
    他提示你“变量'OverHour'赋的值从来没有使用过。”这是编译器的提示,他告诉你OverHour虽然定义了,但是没有被使用过,所以呢这个变量被优化掉了,也就是编译器不会给这个变量分配空间,你的程序中也不存在这个变量。
    所以不能设置断点也就不奇怪了。你后面的几个用到'OverHour'的地方把'//'注释号去掉就可以调了.
      

  7.   

    多谢各位前辈指点,问题可能是出在数据库的某个地方,今早我把家里机器上的数据库还原到单位得机器上运行,就没有那个提示了。
    我又分别看了看2个数据库,也没看出什么不同,不知有没有什么办法比较他们。:)
        通过这个问题,发现我需要学习的地方太多了(正如rainsea所说),以后还的苦练啊。
        帖子先结了,再次谢谢各位大哥了!