📄 kaotong.~pas
字号:
unit kaotong;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, Mask, Gauges, DB, DBTables, Grids, DBGrids,inifiles;
type
TForm26 = class(TForm)
GroupBox1: TGroupBox;
Label1: TLabel;
Label2: TLabel;
i_time: TMaskEdit;
i_start_time: TMaskEdit;
Label3: TLabel;
i_end_time: TMaskEdit;
B_stat: TButton;
Gauge1: TGauge;
Button2: TButton;
GroupBox2: TGroupBox;
Seek_by_time: TCheckBox;
Seek_by_person: TCheckBox;
seek_time: TMaskEdit;
Seek_person_id: TMaskEdit;
Seek_person_name: TEdit;
Label4: TLabel;
B_seek: TButton;
DBGrid1: TDBGrid;
T_stat: TTable;
DS_stat: TDataSource;
T_person: TTable;
DS_person: TDataSource;
Q_attend: TQuery;
Q_leave: TQuery;
Q_errand: TQuery;
Q_overtime: TQuery;
T_counter: TTable;
Button1: TButton;
procedure FormCreate(Sender: TObject);
procedure Seek_person_idChange(Sender: TObject);
procedure B_seekClick(Sender: TObject);
procedure B_statClick(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form26: TForm26;
implementation
uses kaoqi;
{$R *.dfm}
procedure TForm26.FormCreate(Sender: TObject);
begin
i_start_time.Text:=DateToStr(now-30); //设置起始时间为一个月前
i_end_time.Text:=DateToStr(now); //设置结束时间为当前时间
i_time.Text:=FormatDateTime('yyyy-mm',now); //设置统计年月
Seek_time.Text:=i_time.Text; //设置查询年月
T_stat.Open; //打开统计数据表
end;
procedure TForm26.Seek_person_idChange(Sender: TObject); //当输入教师号时,检索教师姓名,用于确认输入
begin
T_person.Filter:='ID='''+Seek_person_id.Text+'''';
T_person.Filtered:=True;
T_person.Open;
if T_person.RecordCount=1 then //判断教师信息是否存在
Seek_person_name.Text:=T_person['NAME'] //显示教师姓名
else
Seek_person_name.Text:=''; //清除教师姓名
T_person.Close;
end;
procedure TForm26.B_seekClick(Sender: TObject); //按条件进行检索,用于检索教师信息
var
FilterStr:String;
begin
with T_stat do
begin
close; //关闭统计数据表
FilterStr:=''; //初始化过滤字符串
if Seek_by_person.Checked then //判断时根据教师号过滤
FilterStr:='PERSON='''+Seek_person_id.Text +''''; //添加教师过滤条件
if Seek_by_time.Checked then //判断是否包含时间范围
begin
if length(FilterStr)>0 then FilterStr:=FilterStr+' AND '; //如果已有过滤条件,需添加And连接符
FilterStr:=FilterStr+'YEAR_MONTH='+Seek_time.Text; //设置时间过滤条件
end;
if length(FilterStr)>0 then //判断是否有过滤字符串
begin
Filter:=FilterStr; //设置过滤条件
Filtered:=True;
end
else //如果没有过滤字符串,取消过滤器
Filtered:=False; //打开统计表
Open;
end;
end;
procedure TForm26.B_statClick(Sender: TObject); //整个统计过程
var //变量申明
MyInifile:Tinifile; //用于读写ini文件
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'); //打开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); //转换统计结束时间
//提取员工列表
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) //请假记录计数加1
else if errand then //如果有出差记录
begin
Inc(ErrandHDay); //出差计数加1
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['SUMR'];//提取加班时间
except
OverHour:=0;//如果无加班记录,加班时间为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); //已统计教师数加1
Gauge1.Progress:=(100*i) div n; //显示统计次数
T_person.Next; //跳至下一个教师记录
end; //下一个员工考勤
end;
procedure TForm26.Button2Click(Sender: TObject);
begin
form26.Hide;
form22.show;
end;
procedure TForm26.Button1Click(Sender: TObject);
begin
// showmessage('未到月末或者数据库中的数据表没有填写完全时,结果会出现错误,无法看到统计结果!') ;
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -