各位大哥,小弟现在在练习一个人事管理的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),
小弟苦苦思索却始终找不到错在哪里,各位前辈请指点啊!
小弟多谢了!!!
的模块,其中统计有如下的代码
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),
小弟苦苦思索却始终找不到错在哪里,各位前辈请指点啊!
小弟多谢了!!!
overhour :=Q_overtime.fieldbyname('sumr').AsInteger ;
从错误的提示分析“非法的变量类型转换”的信息看,你的错误出在进行类型转换的时候。从你的程序看strtodate,strtotime疑点较大,所以在这些函数上设上断点就可以了。
事实上,我查遍vcl的源码发现报这个错的函数就是时间转换函数。
难道是数据库的问题?我今天把单位的数据库考到家里的电脑上再试试(不过也不应该啊,单位的overtime表只有4条记录,每条记录都非空啊)。
TO wjlsmail:
你写的那个语句好用。但OverHour:=Q_overtime['SUMR'];在家里的电脑上也好用。
TO findcsdn:
前辈,非常感谢你的答复,但我确实是太菜了,再麻烦问一下在strtodate,strtotime等处设置断点再怎样跟踪调试之类的。另外,在OverHour:=0;那行左边没有小菱形(点一下出来个小红圆里面是叉号而不是对号,右边的代码变成绿色而不是红色),在LeaveHDay:=0;设置断点后,当鼠标移动到前面的变量除了OverHour都能显出值来,惟独移到OverHour上什么也不反应,是不是OverHour有什么问题啊?
小弟多谢了!!!
他提示你“变量'OverHour'赋的值从来没有使用过。”这是编译器的提示,他告诉你OverHour虽然定义了,但是没有被使用过,所以呢这个变量被优化掉了,也就是编译器不会给这个变量分配空间,你的程序中也不存在这个变量。
所以不能设置断点也就不奇怪了。你后面的几个用到'OverHour'的地方把'//'注释号去掉就可以调了.
我又分别看了看2个数据库,也没看出什么不同,不知有没有什么办法比较他们。:)
通过这个问题,发现我需要学习的地方太多了(正如rainsea所说),以后还的苦练啊。
帖子先结了,再次谢谢各位大哥了!