C# winform上下班打卡系統Demo
系統效果如圖所示
7個label控件(lblUsername、lblLoggedInEmployeeId、lab_IP、lblCheckOutTime、lblCheckInTime、lab_starttime、lab_endtime)、3個按鈕、1個dataGridView控件、2個groupBox控件
C#代碼實現
using System;
using System.Data;
using System.Data.SqlClient;
using System.Drawing;
using System.Net;
using System.Net.Sockets;
using System.Runtime.InteropServices;
using System.Windows.Forms;namespace WindowsFormsApp1
{public partial class 員工打卡 : Form{private string loggedInUsername;private string loggedInEmployeeId;private string connectionString = "server=127.0.0.1;uid=sa;pwd=xyz@0123456;database=test";public 員工打卡(string username, string employeeId){InitializeComponent();loggedInUsername = username;loggedInEmployeeId = employeeId;CheckTodaysPunchInRecord();}[DllImport("user32.dll")]public static extern IntPtr GetSystemMenu(IntPtr hWnd, bool bRevert);[DllImport("user32.dll")]public static extern bool EnableMenuItem(IntPtr hMenu, uint uIDEnableItem, uint uEnable);// 禁用窗口大小改變private const uint SC_SIZE = 0xF000;private const uint MF_BYCOMMAND = 0x0000;private const uint MF_GRAYED = 0x0001;protected override void OnLoad(EventArgs e){base.OnLoad(e);IntPtr hMenu = GetSystemMenu(this.Handle, false);if (hMenu != IntPtr.Zero){EnableMenuItem(hMenu, SC_SIZE, MF_BYCOMMAND | MF_GRAYED);}}private void 員工打卡_Load(object sender, EventArgs e){lblUsername.Text = "當前登錄用戶:" + loggedInUsername;lblLoggedInEmployeeId.Text = "工號:" + loggedInEmployeeId.ToString();// 設置日期控件的顯示格式為年-月-日startTime.Format = DateTimePickerFormat.Custom;startTime.CustomFormat = "yyyy-MM-dd";// 設置日期控件的顯示格式為年-月-日endTime.Format = DateTimePickerFormat.Custom;endTime.CustomFormat = "yyyy-MM-dd";//不顯示出dataGridView1的最后一行空白dataGridView1_Result.AllowUserToAddRows = false;// 設置數據和列名居中對齊dataGridView1_Result.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;dataGridView1_Result.ColumnHeadersDefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;// 設置列名加粗dataGridView1_Result.ColumnHeadersDefaultCellStyle.Font = new System.Drawing.Font(dataGridView1_Result.ColumnHeadersDefaultCellStyle.Font, FontStyle.Bold);// 設置列寬自適應dataGridView1_Result.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;LoadData();GetIP();}private void GetIP(){// 獲取本機IP地址IPHostEntry ipHost = Dns.GetHostEntry(Dns.GetHostName());foreach (IPAddress ip in ipHost.AddressList){if (ip.AddressFamily == AddressFamily.InterNetwork){lab_IP.Text = "IP地址:" + ip.ToString(); // 添加到label1的Text屬性中}}}private void btnCheckIn_Click(object sender, EventArgs e){if (IsPunchInRecordExists()){MessageBox.Show("你已打過上班卡。", "提示", MessageBoxButtons.YesNo, MessageBoxIcon.Asterisk);return;}DateTime currentTime = DateTime.Now;string punchInTime = currentTime.ToString("yyyy-MM-dd HH:mm:ss");string status = currentTime.TimeOfDay < new TimeSpan(8, 30, 0) ? "正常" : "遲到";InsertPunchInRecord(punchInTime, status);lblCheckInTime.Text = punchInTime;lblCheckInTime.Visible = true;// 刷新DataGridView顯示最新打卡記錄RefreshDataGridView();}private bool IsPunchInRecordExists(){DateTime currentDate = DateTime.Now.Date;string query = $"SELECT COUNT(*) FROM PunchIn WHERE emp_code='{loggedInEmployeeId}' AND punch_in_time >= '{currentDate}'";using (SqlConnection connection = new SqlConnection(connectionString)){connection.Open();using (SqlCommand command = new SqlCommand(query, connection)){int count = (int)command.ExecuteScalar();return count > 0;}}}private void RefreshDataGridView(){// 執行查詢語句string query = $@"SELECT a.id,a1.username AS 用戶名,a.emp_code AS 工號,CONVERT(VARCHAR(19), a.punch_in_time, 120) AS 上班打卡時間,a.status AS 上班打卡狀態,CONVERT(VARCHAR(19), b.punch_out_time, 120) AS 下班打卡時間,b.status AS 下班打卡狀態FROM (SELECT * FROM Employee) a1LEFT JOIN PunchIn a ON a1.emp_code = a.emp_codeLEFT JOIN PunchOut b ON a.emp_code = b.emp_code AND CONVERT(DATE, a.punch_in_time) = CONVERT(DATE, b.punch_out_time)AND b.punch_out_time = (SELECT MAX(punch_out_time)FROM PunchOutWHERE emp_code = a.emp_code AND CONVERT(DATE, punch_out_time) = CONVERT(DATE, a.punch_in_time))WHERE a.emp_code = '{loggedInEmployeeId}' AND MONTH(a.punch_in_time) = MONTH(GETDATE()) AND YEAR(a.punch_in_time) = YEAR(GETDATE())ORDER BY a.id, a.emp_code, a.punch_in_time";Console.WriteLine("執行的SQL語句是:" + query);// 執行查詢并獲取結果// 你可以使用適合你數據庫的查詢方法DataTable dataTable = ExecuteQuery(query);// 將查詢結果綁定到DataGridView的數據源dataGridView1_Result.DataSource = dataTable;}private DataTable ExecuteQuery(string query){// 創建連接和命令對象并執行查詢using (SqlConnection connection = new SqlConnection(connectionString)){connection.Open();using (SqlCommand command = new SqlCommand(query, connection)){// 創建適配器并填充數據到DataTableSqlDataAdapter adapter = new SqlDataAdapter(command);DataTable dataTable = new DataTable();adapter.Fill(dataTable);return dataTable;}}}private void InsertPunchInRecord(string punchInTime, string status){string query = $"INSERT INTO PunchIn (emp_code, punch_in_time, status) VALUES ('{loggedInEmployeeId}', '{punchInTime}', '{status}')";using (SqlConnection connection = new SqlConnection(connectionString)){connection.Open();using (SqlCommand command = new SqlCommand(query, connection)){command.ExecuteNonQuery();}}}private void CheckTodaysPunchInRecord(){DateTime currentDate = DateTime.Now.Date;string query = $"SELECT punch_in_time FROM PunchIn WHERE emp_code='{loggedInEmployeeId}' AND punch_in_time >= '{currentDate}'";using (SqlConnection connection = new SqlConnection(connectionString)){connection.Open();using (SqlCommand command = new SqlCommand(query, connection)){object result = command.ExecuteScalar();if (result != null){string punchInTime = ((DateTime)result).ToString("yyyy-MM-dd HH:mm:ss");lblCheckInTime.Text = punchInTime;lblCheckInTime.Visible = true;}}}}private void btnCheckOut_Click(object sender, EventArgs e){DateTime currentTime = DateTime.Now;string punchOutTime = currentTime.ToString("yyyy-MM-dd HH:mm:ss");if (IsInvalidPunchOutTime(currentTime)){MessageBox.Show("21點30到23:59:59點打下班卡無效。");return;}string status = currentTime.TimeOfDay < new TimeSpan(18, 0, 0) ? "早退" : "正常"; // 判斷下班打卡時間是否在18:00之前InsertPunchOutRecord(punchOutTime, status);lblCheckOutTime.Text = punchOutTime;lblCheckOutTime.Visible = true;// 刷新DataGridView顯示最新打卡記錄RefreshDataGridView();}private bool IsInvalidPunchOutTime(DateTime currentTime){TimeSpan startTime = new TimeSpan(21, 30, 0);TimeSpan endTime = new TimeSpan(23, 59, 59);TimeSpan currentTimeOfDay = currentTime.TimeOfDay;return currentTimeOfDay >= startTime && currentTimeOfDay <= endTime;}private void InsertPunchOutRecord(string punchOutTime, string status){string query = $"INSERT INTO PunchOut (emp_code, punch_out_time, status) VALUES ('{loggedInEmployeeId}', '{punchOutTime}', '{status}')";using (SqlConnection connection = new SqlConnection(connectionString)){connection.Open();using (SqlCommand command = new SqlCommand(query, connection)){command.ExecuteNonQuery();}}}private void btn_Serch_Click(object sender, EventArgs e){// 獲取所選時間范圍DateTime startDate = startTime.Value.Date;DateTime endDate = endTime.Value.Date.AddDays(1).AddSeconds(-1);// 構建 SQL 查詢語句string query = $@"SELECT a.id,a1.username AS 用戶名,a.emp_code AS 工號,CONVERT(VARCHAR(19), a.punch_in_time, 120) AS 上班打卡時間,a.status AS 上班打卡狀態,CONVERT(VARCHAR(19), b.punch_out_time, 120) AS 下班打卡時間,b.status AS 下班打卡狀態FROM (SELECT * FROM Employee) a1LEFT JOIN PunchIn a ON a1.emp_code = a.emp_codeLEFT JOIN PunchOut b ON a.emp_code = b.emp_code AND CONVERT(DATE, a.punch_in_time) = CONVERT(DATE, b.punch_out_time)AND b.punch_out_time = (SELECT MAX(punch_out_time)FROM PunchOutWHERE emp_code = a.emp_code AND CONVERT(DATE, punch_out_time) = CONVERT(DATE, a.punch_in_time))WHERE a.punch_in_time BETWEEN @StartDate AND @EndDateAND a.emp_code = '{loggedInEmployeeId}'ORDER BY a.id, a.emp_code, a.punch_in_time";using (SqlConnection connection = new SqlConnection(connectionString)){using (SqlCommand command = new SqlCommand(query, connection)){// 添加查詢參數command.Parameters.AddWithValue("@StartDate", startDate);command.Parameters.AddWithValue("@EndDate", endDate);Console.WriteLine("查詢的SQL語句:" + query);// 打開數據庫連接connection.Open();// 創建數據適配器和數據表SqlDataAdapter adapter = new SqlDataAdapter(command);DataTable table = new DataTable();// 填充數據表adapter.Fill(table);// 關閉數據庫連接connection.Close();// 綁定數據表到 DataGridView 控件dataGridView1_Result.DataSource = table;}}}private void LoadData(){// 獲取所選時間范圍DateTime startDate = startTime.Value.Date;DateTime endDate = endTime.Value.Date.AddDays(1).AddSeconds(-1);string query = $@"SELECT a.id,a1.username AS 用戶名,a.emp_code AS 工號,CONVERT(VARCHAR(19), a.punch_in_time, 120) AS 上班打卡時間,a.status AS 上班打卡狀態,CONVERT(VARCHAR(19), b.punch_out_time, 120) AS 下班打卡時間,b.status AS 下班打卡狀態FROM (SELECT * FROM Employee) a1LEFT JOIN PunchIn a ON a1.emp_code = a.emp_codeLEFT JOIN PunchOut b ON a.emp_code = b.emp_code AND CONVERT(DATE, a.punch_in_time) = CONVERT(DATE, b.punch_out_time)AND b.punch_out_time = (SELECT MAX(punch_out_time)FROM PunchOutWHERE emp_code = a.emp_code AND CONVERT(DATE, punch_out_time) = CONVERT(DATE, a.punch_in_time))WHERE a.punch_in_time BETWEEN @StartDate AND @EndDateAND a.emp_code = '{loggedInEmployeeId}'ORDER BY a.id, a.emp_code, a.punch_in_time";Console.WriteLine("開始時間:" + startDate);Console.WriteLine("結束時間:" + endDate);using (SqlConnection connection = new SqlConnection(connectionString)){using (SqlCommand command = new SqlCommand(query, connection)){// 添加查詢參數command.Parameters.AddWithValue("@StartDate", startDate);command.Parameters.AddWithValue("@EndDate", endDate);Console.WriteLine("一加載時獲取數據查詢的SQL語句:" + query);// 打開數據庫連接connection.Open();// 創建數據適配器和數據表SqlDataAdapter adapter = new SqlDataAdapter(command);DataTable table = new DataTable();// 填充數據表adapter.Fill(table);// 關閉數據庫連接connection.Close();// 綁定數據表到 DataGridView 控件dataGridView1_Result.DataSource = table;}}}}
}