?? statdlg.cpp
字號:
// StatDlg.cpp : implementation file
//
#include "stdafx.h"
#include "Attendance.h"
#include "StatDlg.h"
#include "PersonRS.h"
#include "CounterRS.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
extern CDatabase db;
extern CTime StrToTime(CString str);
/////////////////////////////////////////////////////////////////////////////
// CStatDlg dialog
CStatDlg::CStatDlg(CWnd* pParent /*=NULL*/)
: CDialog(CStatDlg::IDD, pParent)
{
CTime End_t=CTime::GetCurrentTime(); // 當前時間
CTimeSpan tp(30,0,0,0); // 時間間隔為30天
//{{AFX_DATA_INIT(CStatDlg)
m_strTime = End_t.Format("%Y-%m");
m_STime = End_t-tp;
m_ETime = End_t;
m_bSeekbytime = FALSE;
m_bSeekbyperson = FALSE;
m_strSeektime = _T("");
m_strPersonID = _T("");
m_strPersonName = _T("");
//}}AFX_DATA_INIT
}
void CStatDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CStatDlg)
DDX_Control(pDX, IDC_STAT_PROGRESS, m_cProgress);
DDX_Control(pDX, IDC_STAT_LIST, m_cList);
DDX_Text(pDX, IDC_STAT_EDT_TIME, m_strTime);
DDX_DateTimeCtrl(pDX, IDC_STAT_DATETIMEPICKER_STARTTIME, m_STime);
DDX_DateTimeCtrl(pDX, IDC_STAT_DATETIMEPICKER_ENDTIME, m_ETime);
DDX_Check(pDX, IDC_STAT_CHK_SEEKBYTIME, m_bSeekbytime);
DDX_Check(pDX, IDC_STAT_CHK_SEEKBYPERSON, m_bSeekbyperson);
DDX_Text(pDX, IDC_STAT_EDT_SEEKTIME, m_strSeektime);
DDX_Text(pDX, IDC_STAT_EDT_SEEKPERSONID, m_strPersonID);
DDX_Text(pDX, IDC_STAT_EDT_SEEKPERSONNAME, m_strPersonName);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CStatDlg, CDialog)
//{{AFX_MSG_MAP(CStatDlg)
ON_EN_CHANGE(IDC_STAT_EDT_SEEKPERSONID, OnChangeStatEdtSeekpersonid)
ON_BN_CLICKED(IDC_STAT_BTN_SEEK, OnStatBtnSeek)
ON_BN_CLICKED(IDC_STAT_BTN_STAT, OnStatBtnStat)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CStatDlg message handlers
void CStatDlg::OnChangeStatEdtSeekpersonid()
{
UpdateData(); // 更新數據
CPersonRS rs(&db); // 構造記錄集
rs.m_strFilter = "ID='" + m_strPersonID + "'"; // 設置過濾條件
rs.Open(); // 打開記錄集
if(rs.GetRecordCount()==1) // 判斷員工記錄是否存在
{
m_strPersonName=rs.m_NAME; // 得到員工姓名
}
else m_strPersonName.Empty(); // 清除員工姓名的顯示
rs.Close(); // 關閉記錄集
UpdateData(FALSE); // 更新界面數據
}
void CStatDlg::OnStatBtnSeek()
{
CString strFilter; // 保存過濾字符串
CStatRS rs(&db); // 構造統(tǒng)計數據表
UpdateData(); // 更新數據
// 判斷根據員工號過濾
if(m_bSeekbyperson) strFilter="PERSON='" + m_strPersonID + "'";
// 判斷根據年月過濾
if(m_bSeekbytime)
{
if(!strFilter.IsEmpty()) // 如果已有過濾條件
strFilter += " and "; // 需添加and連接符
// 設置時間過濾條件
strFilter += "YEAR_MONTH=#" + m_strSeektime + "#";
}
if(!strFilter.IsEmpty()) // 判斷是否有過濾字符串
{
rs.m_strFilter=strFilter; // 設置過濾條件
}
UpdateList(rs); // 更新列表框
}
BOOL CStatDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// 為List添加網格
m_cList.SetExtendedStyle(LVS_EX_GRIDLINES);
// 設置List的列
int nWidth=100;
m_cList.InsertColumn(0, "記錄編號", LVCFMT_LEFT, 80);
m_cList.InsertColumn(1, "員工號", LVCFMT_LEFT, 50);
m_cList.InsertColumn(2, "年月", LVCFMT_LEFT, nWidth);
m_cList.InsertColumn(3, "正常工作時間(小時)", LVCFMT_LEFT, nWidth+40);
m_cList.InsertColumn(4, "加班時間(小時)", LVCFMT_LEFT, nWidth);
m_cList.InsertColumn(5, "請假時間(半天)", LVCFMT_LEFT, nWidth);
m_cList.InsertColumn(6, "出差時間(半天)", LVCFMT_LEFT, nWidth);
m_cList.InsertColumn(7, "遲到次數", LVCFMT_LEFT, nWidth-30);
m_cList.InsertColumn(8, "早退次數", LVCFMT_LEFT, nWidth-30);
m_cList.InsertColumn(9, "曠工次數", LVCFMT_LEFT, nWidth-30);
CStatRS rs(&db); // 構造出勤記錄表
UpdateList(rs); // 更新List
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
void CStatDlg::UpdateList(CStatRS& rs)
{
int i=0;
CString str;
rs.Open(); // 打開統(tǒng)計數據表
m_cList.DeleteAllItems(); // 清除列表框內容
while(!rs.IsEOF()) // 對數據表中所有記錄進行處理
{
m_cList.InsertItem(i, ""); // 添加新Item
str.Format("%d", rs.m_ID); // 轉換為字符串
m_cList.SetItemText(i, 0, str);
m_cList.SetItemText(i, 1, rs.m_PERSON);
m_cList.SetItemText(i, 2, rs.m_YEAR_MONTH);
str.Format("%d", rs.m_WORK_HOUR);
m_cList.SetItemText(i, 3, str);
str.Format("%d", rs.m_OVER_HOUR);
m_cList.SetItemText(i, 4, str);
str.Format("%d", rs.m_LEAVE_HDAY);
m_cList.SetItemText(i, 5, str);
str.Format("%d", rs.m_ERRAND_HDAY);
m_cList.SetItemText(i, 6, str);
str.Format("%d", rs.m_LATE_TIMES);
m_cList.SetItemText(i, 7, str);
str.Format("%d", rs.m_EARLY_TIMES);
m_cList.SetItemText(i, 8, str);
str.Format("%d", rs.m_ABSENT_TIMES);
m_cList.SetItemText(i, 9, str);
rs.MoveNext(); // 跳到下一條記錄
i++;
}
rs.Close(); // 關閉統(tǒng)計數據表
}
void CStatDlg::OnStatBtnStat()
{
CRecordset rs_Q_attend(&db); // 構造Q_attend記錄集
CRecordset rs_Q_leave(&db); // 構造Q_leave記錄集
CRecordset rs_Q_errand(&db); // 構造Q_errand記錄集
CTimeSpan tp_1(1,0,0,0); // 構造一個1天的CTimeSpan
CTimeSpan tp_02(0,2,0,0); // 構造一個2小時的CTimeSpan
CTimeSpan TimeSpan[4]; // 保存上下班時間
int nHours[2]; // 保存上下午工作時間
CString strSTime,strETime; // 保存始末時間
CTime TimeStamp, LateTime, EarlyTime,WorkStart,WorkEnd; // 保存中間判斷時間
int nWorkHour,nOverHour,nLeaveHDay,nErrandHDay; // 保存時間間隔長度
BOOL bLate,bEarly,bAbsent,bLeave,bErrand; // 保存判斷結果
int nLateTimes,nEarlyTimes,nAbsentTimes; // 保存次數
CString cstr[4]; // 暫存起始時間
char str[4][9]; // 暫存起始時間
int i,j,n,counter; // 用于循環(huán)和計數
CString strTmp,strTmp1,strTmp2; // 臨時變量
// 臨時變量,年,月,日,時,分,秒
int nHour,nMinute,nSecond;
CString strFileName=".\\workplan.ini"; // INI文件名
UpdateData(); // 更新數據
// 讀取INI文件
GetPrivateProfileString("WorkPlan", "Time1", "08:00:00", str[0], 9, strFileName);
GetPrivateProfileString("WorkPlan", "Time2", "12:00:00", str[1], 9, strFileName);
GetPrivateProfileString("WorkPlan", "Time3", "14:00:00", str[2], 9, strFileName);
GetPrivateProfileString("WorkPlan", "Time4", "18:00:00", str[3], 9, strFileName);
for(i=0; i<4; i++) cstr[i]=str[i];
// 定義四個時間間隔變量并初始化為INI文件中的值
CTimeSpan *pTS;
for(i=0; i<4; i++)
{
sscanf(cstr[i].Left(2), "%d", &nHour); // 得到時
sscanf(cstr[i].Mid(3,2), "%d", &nMinute); // 得到分
sscanf(cstr[i].Mid(6,2), "%d", &nSecond); // 得到秒
// 構造一個時間間隔變量
pTS=new CTimeSpan(0,nHour,nMinute,nSecond);
TimeSpan[i]=*pTS; // 賦值
delete pTS;
}
nHours[0]=(TimeSpan[1]-TimeSpan[0]).GetTotalHours(); // 計算上午工作時間
if((TimeSpan[1]-TimeSpan[0]).GetMinutes()>30) nHours[0]++; // 四舍五入
nHours[1]=(TimeSpan[3]-TimeSpan[2]).GetTotalHours(); // 計算下午工作時間
if((TimeSpan[3]-TimeSpan[2]).GetMinutes()>30) nHours[1]++; // 四舍五入
// 轉換統(tǒng)計開始時間
strSTime="#"+m_STime.Format("%Y-%m-%d")+"#";
// 轉換統(tǒng)計結束時間,且天數加1
strETime="#"+(m_ETime+tp_1).Format("%Y-%m-%d")+"#";
// 提取員工列表
CPersonRS rs_person(&db); // 構造員工表
rs_person.m_strFilter="STATE='T'"; // 設置過濾器,提取員工列表
rs_person.Open(); // 打開員工表
n=rs_person.GetRecordCount(); // 記錄員工人數
i=0; // 初始化已處理員工人數
m_cProgress.SetRange(0,n); // 設置進度條
m_cProgress.SetPos(0); // 初始化進度條
while(!rs_person.IsEOF()) // 依次對每個員工進行統(tǒng)計
{
//獲取出勤記錄
// 執(zhí)行查詢
rs_Q_attend.Open(CRecordset::forwardOnly,
"select IN_OUT,IO_TIME from ATTENDANCE\
where PERSON='" + rs_person.m_ID
+ "' and IO_TIME>" + strSTime
+ " and IO_TIME<" +strETime
+ " order by IO_TIME");
strTmp1.Empty(); // 清空strTmp1
// 初始化
nWorkHour=nOverHour=0;
nLeaveHDay=nErrandHDay=0;
nLateTimes=nEarlyTimes=nAbsentTimes=0;
TimeStamp=m_STime; // 初始化時間戳為統(tǒng)計開始時間
while(TimeStamp < m_ETime+tp_02) // 判斷是否超出統(tǒng)計結束時間
{
if(TimeStamp.GetDayOfWeek()!=1 &&
TimeStamp.GetDayOfWeek()!=7) // 判斷是否工作日
{
for(j=0;j<=1;j++) // 遍歷班次
{
LateTime=TimeStamp+TimeSpan[2*j]; // 設置遲到時間
EarlyTime=TimeStamp+TimeSpan[2*j+1]; // 設置早退時間
// 判斷是否請假
rs_Q_leave.Open(CRecordset::forwardOnly,
"select ID from LEAVE where\
PERSON='" + rs_person.m_ID
+ "' and START_TIME<#"
+ LateTime.Format("%Y-%m-%d %H:%M:%S")
+ "# and END_TIME>#"
+ EarlyTime.Format("%Y-%m-%d %H:%M:%S")
+ "#");
bLeave=(rs_Q_leave.GetRecordCount()>0); // 判斷是否有請假記錄
rs_Q_leave.Close(); // 關閉記錄集
// 判斷是否出差
rs_Q_errand.Open(CRecordset::forwardOnly,
"select ID from ERRAND where\
PERSON='" + rs_person.m_ID
+ "' and START_TIME<#"
+ LateTime.Format("%Y-%m-%d %H:%M:%S")
+ "# and END_TIME>#"
+ EarlyTime.Format("%Y-%m-%d %H:%M:%S")
+ "#");
bErrand=(rs_Q_errand.GetRecordCount()>0); // 判斷是否有出差記錄
rs_Q_errand.Close(); // 關閉記錄集
if(bLeave) // 如果有請假記錄
nLeaveHDay++; // 請假記錄加1
else if(bErrand) // 如果有出差記錄
{
nErrandHDay++; // 出差計數加1
nWorkHour+=nHours[j]; // 按正常班累加工作時間
}
else // 正常上班
{
WorkStart=LateTime; // 設置工作開始時間
WorkEnd=EarlyTime; // 設置工作結束時間
bLate=TRUE; // 初始化遲到判斷
bAbsent=FALSE; // 初始化曠工判斷
// 判斷是否遲到
if(!rs_Q_attend.IsEOF() && // 記錄集不空
strTmp1.IsEmpty()) // 空,第一次GetFieldValue
rs_Q_attend.GetFieldValue("IO_TIME",strTmp1); // 得到IO_TIME
while(!rs_Q_attend.IsEOF()
&& StrToTime(strTmp1)<=LateTime)
{// 根據時間順序判斷是否遲到
// 得到IN_OUT
rs_Q_attend.GetFieldValue("IN_OUT",strTmp2);
bLate=(strTmp2=="O"); // 判斷上班時間前是否報到
rs_Q_attend.MoveNext(); // 跳到下一條出勤記錄
// 得到IO_TIME
if(!rs_Q_attend.IsEOF())
rs_Q_attend.GetFieldValue("IO_TIME",strTmp1);
}
// 判斷是否曠工
if(bLate) // 判斷是否遲到
{
if(!rs_Q_attend.IsEOF() && StrToTime(strTmp1)<EarlyTime)
WorkStart=StrToTime(strTmp1); // 記錄遲到時間
else bAbsent=TRUE; // 如果下班前仍未報到記為曠工
}
bEarly=FALSE;
// 判斷是否早退
while(!rs_Q_attend.IsEOF() && StrToTime(strTmp1)<EarlyTime)
{
// 得到IN_OUT
rs_Q_attend.GetFieldValue("IN_OUT",strTmp2);
bEarly=(strTmp2=="O"); // 判斷是否有早退
if(bEarly)
{
// 將早退時間記錄為工作結束時間
WorkEnd=StrToTime(strTmp1);
}
else WorkEnd=EarlyTime; // 將下班時間記錄為工作結束時間
rs_Q_attend.MoveNext(); // 跳至下一條出勤記錄
// 得到IO_TIME
if(!rs_Q_attend.IsEOF())
rs_Q_attend.GetFieldValue("IO_TIME",strTmp1);
}
// 如果曠工,增加曠工次數記錄
if(bAbsent) nAbsentTimes++;
else
{
// 如果遲到,增加遲到次數記錄
if(bLate) nLateTimes++;
// 如果早退,增加早退次數記錄
if(bEarly) nEarlyTimes++;
// 計算實際工作時間
nWorkHour+=(WorkEnd-WorkStart).GetTotalHours();
if((WorkEnd-WorkStart).GetMinutes()>30)
nWorkHour++; // 四舍五入
}
}
} // End of 遍歷班次
} // End of 是否工作日
TimeStamp+=tp_1; // 推進一天
} // End of TimeStamp < m_ETime+tp_02
rs_Q_attend.Close(); // 關閉Q_attend記錄集
// 統(tǒng)計加班時間
CRecordset rs_Q_overtime(&db); // 構造Q_overtime記錄集
rs_Q_overtime.Open(CRecordset::forwardOnly,
"select sum(WORK_HOURS) as SUM from OVERTIME\
where PERSON='" + rs_person.m_ID
+ "' and WORK_DATE>#"
+ m_STime.Format("%Y-%m-%d %H:%M:%S")
+ "# and WORK_DATE<#"
+ m_ETime.Format("%Y-%m-%d %H:%M:%S")
+ "#");
if(rs_Q_overtime.GetRecordCount()>0) // 有記錄
{
// 提取加班時間
rs_Q_overtime.GetFieldValue("SUM",strTmp);
sscanf(strTmp,"%d",&nOverHour);
}
else nOverHour=0; // 無記錄
rs_Q_overtime.Close();
// 判斷是否已有該月考勤記錄
CStatRS rs_stat(&db); // 構造統(tǒng)計數據表
// 設置過濾串
rs_stat.m_strFilter="PERSON='" + rs_person.m_ID
+ "' and YEAR_MONTH='" + m_strTime + "'";
rs_stat.Open(); // 打開數據表
if(rs_stat.GetRecordCount()==0) // 判斷是否有該月份考勤記錄
{
// 獲取計數
CCounterRS rs_counter(&db); // 構造計數器表
rs_counter.m_strFilter = "ID='S'"; // 設置過濾器,提取計數值
rs_counter.Open(); // 打開計數器記錄表
counter=rs_counter.m_COUNTER_VALUE; // 提取計數值
counter++; // 計數值加1
rs_counter.Edit(); // 編輯計數器
rs_counter.m_COUNTER_VALUE=counter; // 保存當前計數
rs_counter.Update(); // 提交修改
rs_counter.Close(); // 關閉計數器記錄表
// 追加統(tǒng)計記錄
rs_stat.AddNew();
rs_stat.m_ID=counter;
rs_stat.m_YEAR_MONTH=m_strTime;
rs_stat.m_PERSON=rs_person.m_ID;
rs_stat.m_WORK_HOUR=nWorkHour;
rs_stat.m_OVER_HOUR=nOverHour;
rs_stat.m_LEAVE_HDAY=nLeaveHDay;
rs_stat.m_ERRAND_HDAY=nErrandHDay;
rs_stat.m_LATE_TIMES=nLateTimes;
rs_stat.m_EARLY_TIMES=nEarlyTimes;
rs_stat.m_ABSENT_TIMES=nAbsentTimes;
rs_stat.Update(); // 提交修改
}
else
{
// 記錄已存在修改數據
rs_stat.Edit();
rs_stat.m_WORK_HOUR=nWorkHour;
rs_stat.m_OVER_HOUR=nOverHour;
rs_stat.m_LEAVE_HDAY=nLeaveHDay;
rs_stat.m_ERRAND_HDAY=nErrandHDay;
rs_stat.m_LATE_TIMES=nLateTimes;
rs_stat.m_EARLY_TIMES=nEarlyTimes;
rs_stat.m_ABSENT_TIMES=nAbsentTimes;
rs_stat.Update(); // 提交修改
}
rs_stat.Close(); // 關閉數據表
i++; // 已統(tǒng)計員工數加1
m_cProgress.SetPos(i); // 顯示統(tǒng)計進度
rs_person.MoveNext(); // 跳到下一個員工記錄
}
rs_person.Close(); // 關閉員工表
CStatRS rs_stat(&db); // 構造統(tǒng)計數據表
UpdateList(rs_stat); // 更新列表框
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -