Hàm chấm công (1 người xem)

Liên hệ QC

Người dùng đang xem chủ đề này

handung107

Thành viên gắn bó
Thành viên danh dự
Tham gia
30/5/06
Bài viết
1,630
Được thích
17,442
Nghề nghiệp
Bác sĩ
Lê Văn Duyệt​

Vấn đề:

Ở một số công ty, nhà máy nhỏ việc chấm công thông thường được thực hiện trên Excel. Qua trao đổi tôi thấy rằng đa số khi nhân viên có đi làm thì sẽ được chấm là X , nghĩ phép là P , ...vv. Sau đó sẽ sử dụng một số hàm trong Excel để tính số ngày công trong một tháng của nhân viên. Tôi nghĩ rằng thông thường số ngày làm việc sẽ nhiều hơn số ngày nghĩ, nếu chấm công như trên nghĩa là bạn phải nhập vào bảng tính Excel nhiều hơn nếu bạn chỉ nhập vào những ngày nghĩ của nhân viên ấy. Giả sử rằng trong một ngày nhân viên nghĩ phép ½ ngày, sau đó do nhu cầu công việc yêu cầu họ tăng ca 3 tiếng thì công việc chấm công sẽ như thế nào. Tôi thấy một số nơi sẽ đưa việc chấm tăng ca qua một sheet khác, hay bảng dữ liệu khác...Hoặc có những ngày thì tính công nhật (công thời gian), có những ngày tính theo năng suất...thì bạn phải làm như thế nào. Tôi nghĩ ở một số công ty việc chấm công sẽ rắc rối hơn như trên vì hiện nay ở một số công ty có cả công nhân thời vụ và công nhân chính thức,...!

Vâng, vấn đề chắc chắn là rắc rối. Ở đây tôi không có tham vọng giải quyết tất cả các vấn đề trên. Tôi chỉ muốn đưa ra hàm chấm công để cho công việc chấm công dễ dàng hơn.
 
Cấu trúc của hàm chấm công như sau:

Public Function Chamcong(ByVal Khoang As Range, ByVal Chucnang As String) As Single
_ Khoang: là khoảng (Thông thường là một hàng từ cột...đến cột...) tương ứng với hàng hay khoảng mà bạn chấm công cho một nhân viên.

_ Chucnang: là chuổi hay ký tự đại diện cho một chức năng chấm công của bạn.

Giả sử ở đây tôi quy định:

Nghĩ phép là: A

Nghĩ bệnh là: S

Nghĩ ma chay là: C

Nghĩ không lương là: U

Tăng ca ngày thường (tính nhân cho 1.5) là: N

Tăng ca ngày nghĩ (tính nhân cho 2) là: D

Vậy nếu trong một ngày nhân viên đó nghĩ phép ½ ngày, tăng ca (ngày thường) 3 tiếng thì tôi sẽ chấm như sau: (Giả sử tên nhân viên là Triệu Nhất Đông, ngày áp dụng là 27/02/2002)

Ở đây việc chấm công cho nghĩ phép và tăng ca sẽ được cách nhau bởi “ ; “ (dấu chấm phẩy, nếu bạn muốn bạn cũng có thể thay đổi ký tự trên khi bạn khai báo để xử lý trong hàm chấm công).
 
Upvote 0
Lê Văn Duyệt Post :

Trong hàm chấm công của tôi, tôi có sử dụng một Class tên clsString của Thấy Lê Đức Hồng (HTTP: www.vovisoft.com).
Bạn chỉ việc copy đoạn mã sau và đưa vào class module trong cửa sổ VBE của bạn.

Author: Le Duc Hong http://www.vovisoft.com
Mã:
Option Explicit 
Private SText As String 
Private SDelimiter As String 
Private IPos As Integer 
Private ILen As Integer 
Public MaxToken As Integer 
Private Tokens() As String 
Public Property Get Text() As Variant 
Text = SText 
End Property 
Public Property Let Text(ByVal vNewValue As Variant) 
SText = vNewValue 
ILen = Len(SText): IPos = 1 
End Property 
Public Property Get Delimiter() As Variant 
Delimiter = SDelimiter 
End Property 
Public Function TokenAt(TNum) As String 
If (TNum > 0) And (TNum <= MaxToken) Then 
TokenAt = Tokens(TNum) 
Else 
TokenAt = "" 
End If 
End Function 
Public Property Let Delimiter(ByVal vNewValue As Variant) 
SDelimiter = vNewValue 
Tokenise 
End Property 
Private Sub Tokenise() 
Dim i 
i = 0: IPos = 1 
Do Until IPos > ILen 
i = i + 1 
ReDim Preserve Tokens(i) 
Tokens(i) = GetToken 
Loop 
MaxToken = i 
IPos = 1 
End Sub 
Public Sub ReplaceToken(TNum, NewToken) 
If (TNum > 0) And (TNum <= MaxToken) Then 
Tokens(TNum) = NewToken 
ReconstructText 
End If 
End Sub 
Private Sub ReconstructText() 
Dim i 
SText = "" 
For i = 1 To MaxToken 
SText = SText & Tokens(i) 
If i < MaxToken Then SText = SText & SDelimiter 
Next 
End Sub 
Public Function KeepLeftPart(NumChar) As String 
If ILen >= NumChar Then 
SText = Left(SText, NumChar): ILen = Len(SText) 
End If 
KeepLeftPart = SText 
End Function 
Public Function KeepRightPart(NumChar) As String 
If ILen >= NumChar Then 
SText = Right(SText, NumChar): ILen = Len(SText) 
End If 
KeepRightPart = SText 
End Function 
Public Function KeepMidPart(SPos, NumChar) As String 
If ILen >= SPos Then 
SText = Mid(SText, SPos): ILen = Len(SText) 
End If 
If ILen >= NumChar Then 
SText = Right(SText, NumChar) 
End If 
KeepMidPart = SText 
End Function 
Public Property Get CurrentPos() As Variant 
CurrentPos = IPos 
End Property 
Public Property Let CurrentPos(ByVal vNewValue As Variant) 
IPos = vNewValue 
End Property 
Public Function GetToken() As String 
Dim Pos 
GetToken = "" 
If SDelimiter = " " Then 
Do While Mid(SText, IPos, 1) = " " 
IPos = IPos + 1 
If IPos > ILen Then 
Exit Function 
End If 
Loop 
End If 
Pos = InStr(IPos, SText, SDelimiter) 
If Pos > 0 Then 
GetToken = Mid(SText, IPos, Pos - IPos) 
IPos = Pos + Len(SDelimiter) 
Else 
GetToken = Mid(SText, IPos, ILen - IPos + 1) 
IPos = ILen + 1 
End If 
End Function 
Public Sub Substitude(Param, ParamValue) 
Dim Pos, PLen 
PLen = Len(Param) 
Pos = InStr(SText, Param) 
Do While Pos > 0 
SText = Left(SText, Pos - 1) & ParamValue & Mid(SText, Pos + PLen) 
Pos = InStr(SText, Param) 
Loop 
ILen = Len(SText) 
End Sub 
Public Function GetLastToken() As String 
Dim Pos, Tlen 
Tlen = Len(SDelimiter) 
GetLastToken = "" 
If ILen = 0 Then 
Exit Function 
End If 
Pos = ILen - Tlen + 1 
Do While Pos > 0 
If Mid(SText, Pos, Tlen) = SDelimiter Then 
GetLastToken = Mid(SText, Pos + Tlen) 
End If 
Pos = Pos - 1 
Loop 
End Function 
Public Property Get Length() As Integer 
Length = ILen 
End Property 
Public Property Get TokenCount() As Variant 
TokenCount = MaxToken 
End Property
 
Chỉnh sửa lần cuối bởi điều hành viên:
Upvote 0
Lê Văn Duyệt Post :

Sau đó bạn bạn copy đoạn mã hàm chấm công sau vào trong module của bạn.
Mã:
Public Function Chamcong(ByVal Khoang As Range, ByVal Chucnang As String) As Single 
Dim Socot As Integer, Sohang As Integer 
Dim i As Integer, j As Integer, k As Integer 
Dim Btotal As Single 
Dim Bgiatriso As Single 
Dim Bchucnang As String 
Dim SoLoai As Byte ' Bien nay nham xac dinh so loai ngay nghi, tang ca... trong mot chuoi
Dim BChuoi As clsString 
Dim BGiatri 
On error resume next 
'Xac dinh so cot trong bien Khoang
Socot = Khoang.Columns.Count 
'Xac dinh so hang trong bien Khoang
Sohang = Khoang.Rows.Count 
' Nham bao dam so sanh dung ta dung ham UCase
Chucnang = UCase(Chucnang) 
'Duyet qua cac cell trong bien Khoang
For i = 1 To Sohang 
For j = 1 To Socot 
BGiatri = Khoang.Cells(i, j).Value 
BGiatri = Trim(BGiatri) 
' Bat dau xu ly bgiatri qua Class clsString
Set BChuoi = New clsString 
BChuoi.Text = BGiatri 
'Ky tu de phan cach cac Chuc nang
BChuoi.Delimiter = ";" 
'Xac dinh so Chuc nang trong 1 cell
SoLoai = BChuoi.TokenCount 
For k = 1 To SoLoai 
'Chuoi cua tung chuc nang
BGiatri = BChuoi.TokenAt(k) 
Bchucnang = UCase(Left(BGiatri, Len(Chucnang))) 
Bgiatriso = Val(Right(BGiatri, Len(BGiatri) - len(Chucnang))) 
Select Case Bchucnang 
Case Chucnang 
Btotal = Btotal + Bgiatriso 
End Select 
Next k 
Next j 
Next i 
Chamcong = Btotal 
End Function
Với hàm chấm công như trên, bạn có thể dùng các chuổi ký tự dài hơn để thể hiện chức năng mà bạn cần (Ví dụ như: nghiphep, nghibenh, tangca,...vv), hay trong công thức bạn có thể tham chiếu đến một cell nào đó để đại diện cho chức năng bạn muốn.

Trong ví dụ này, ngày 22/02 tôi chấm công nghiphep1, ngày 23/02 tôi chấm công nghiphep0.5;tangca3. Công thức trong ô AM8, tôi sẽ nhập vào

Mã:
=chamcong(G8:AH8,AM7)
(ô AM7 chứa chữ Nghiphep)

Công thức trong ô AN8, tôi nhập công thức sau:

Mã:
=chamcong(G8:AH8,AN7)
(ô AN7 chứa chữ Tangca)

Vâng, dĩ nhiên là bạn có thể sử dụng các chuổi ký tự như trên sẽ dễ hiểu, nhưng bảng chấm công của bạn sẽ rất lượm thuộm.

Tôi hy vọng rằng bài viết trên sẽ giúp ích các bạn phần nào trong công việc chấm công nhàm chán (nhưng không được sai) hàng ngày của bạn.

Ngòai chức năng trên, hàm này còn làm được nhiều chức năng khác tùy từng ứng dụng của bạn.

Mọi ý kiến góp ý xin các bạn gởi về:

levanduyet@yahoo.com
 
Chỉnh sửa lần cuối bởi điều hành viên:
Upvote 0
Lê Văn Duyệt Post :

Dùng Format Conditional... để định dạng cột ngày Chủ nhật trong bảng chấm công​

Tôi xin giới thiệu với các bạn việc sử dụng Format conditional... để thay đổi định dạng của cột ngày Chủ nhật trong bảng chấm công.

Thông thường ngoài các cột như mã nhân viên, tên nhân viên,...thì bảng chấm công sẽ có các cột thể hiện các ngày trong tháng. Tôi muốn rằng qua năm sau tôi lại sử dụng lại các sheet này để làm bảng chấm công cho năm . Do đó nếu tôi làm công việc thủ công là chọn cột các ngày là ngày Chủ nhật trong tháng, rồi Fill color thì công việc thật là nhàm chán. Tôi muốn là tôi chỉ thay đổi ngày đầu tiên của bảng chấm công thì nó sẽ tự động thay đổi màu của các cột trong bảng chấm công là ngày Chủ nhật.

Giả sử bảng chấm công của tôi như sau:



Trong ô C4 tôi nhập ngày đầu tiên của bảng chấm công. Ô C5 tôi nhập công thức sau: =C4+1, sau đó tôi copy công thức này qua các ô bên phải (các ô C6, C7, C8,...). Chọn khoảng cần định dạng trong bảng chấm công, giả sử ở đây tôi chọn khoảng C5:Q20. Sau đó chọn Format | Conditional...

Rồi sau đó nhập công thức và chọn Format như hình sau. Sau đó chọn OK.


Sau đó các bạn thử bằng cách, thay ô C4 bằng các ngày khác thì việc tô màu các cột là ngày Chủ nhật cũng sẽ thay đổi sau.

Chúc các bạn vui với điều mình vừa khám phá.

Lê Văn Duyệt

Mọi góp ý các bạn gởi về levanduyet@yahoo.com
 
Upvote 0
Em có một chút thắc mắc rất mong được mọi người giúp đỡ. Ngoài ngày chủ nhật thì ở một số doanh nghiệp còn được nghỉ thứ bảy cộng thêm những ngày lễ trong năm như mùng 2 tháng 9 hay tết dương lịch và âm lịch và những ngày nghỉ đặc thù của doanh nghiệp đó. Vậy thì có thể dùng Conditional Formatting được không? Nếu được thì phải làm như thế nào. Cảm ơn các anh.
 
Upvote 0
Âm lịch thì khó đó!

Ngoài ngày chủ nhật thì ở một số doanh nghiệp còn được nghỉ thứ bảy cộng thêm những ngày lễ trong năm như mùng 2 tháng 9 hay tết dương lịch và âm lịch và những ngày nghỉ đặc thù của doanh nghiệp đó. Vậy thì có thể dùng Conditional Formatting được không? Nếu được thì phải làm như thế nào. Cảm ơn các anh.
Các ngày dương thì có vẻ dễ, phải không các bạn;
(ác ngày âm thì rắt rối đây;Nhưng dù sau cũng đã có người viết hàm chuyển từ ngày dương sang ngày âm rồi (tìm trên diễn đàn = từ khóa 'âm lịch')
(húc &ui!
 
Upvote 0
Giải pháp đơn giản kinh khủng. Bạn có 1 table có tên là tb_Holidays. Trong đó bạn sẽ nhập các ngày lễ trong năm

tb_Holidays có những trường sau:
- WorkingYear
- HolidayDate
- Note

Khi chấm công (quẹt thẻ hoặc chấm công tay) thì sẽ phải check thông tin ngày vào bảng Holidays xem ngày đó có phải là ngày lễ hay ko. Đơn giản thế thôi. Còn chuyện xác định 1 năm có bao nhiêu ngày lễ (trong đó có ngày lễ của công ty) thì quá đơn giản (1 năm nhập có khoảng 6 hay 7 dòng gì đó), cần gì phải lịch âm-dương làm gì cho mệt. (Chú ý, ngày lễ khác với ngày nghỉ thứ 7, chủ nhật nhé. Chỉ cần thêm 1 chút luật về ngày nghỉ theo tuần, theo tháng là xong vấn đề ngày nghỉ, ngày lễ rồi (để xác định ra OT150%, OT180%,... gì đó ấy mà)
 
Upvote 0
Món này đồng ý với Hai2Hai... Âm lịch quá phí trong trường hợp này vì 1 năm có bao nhiêu ngày lễ âm lịch đâu... Nhập bằng tay vào bảng Index cũng ko phải là tốn công gì lắm
Tôi vẫn đang làm thế cho việc tạo lịch đại tu định kỳ (1 năm thay đỗi 1 lần, mà cũng chỉ thay đỗi với âm lịch)
Còn nữa: Dù có hàm tính âm lịch cũng sẽ ko khả thi (ít nhất là với cty tôi)... ví dụ ngày lễ Giỗ tổ Hùng Vương, theo luật thì sẽ nghĩ vào ngày nào đó... nhưng cty lại sắp xếp lại, ngày ấy đi làm, nghĩ bù vào 1 ngày khác... vậy thà gõ tay vào còn sướng hơn
ANH TUẤN
 
Lần chỉnh sửa cuối:
Upvote 0
Có anh chị nào có một VD cụ thể về hàm chấm công như hướng dẫn của Chị HD bên trên không, post lên cho chúng em học hỏi với
Tks.
 
Upvote 0
Xin chào các anh chị,
Mình đã tham khảo về cách chấm công trong excel mình đang có một problem với phần theo dõi phép. Vấn đề như sau:

Công ty mình theo dõi phép của năm 2007 chuyển sang năm 2008 nhưng chỉ sử dụng trong tháng 1,2,3, sang tháng 4 phép 2007 coi như bằng 0(nếu không dùng hết). Còn phép 2008 tính bình thường.

Mình muốn dùng trên 1 sheet và chỉ 2 cột để theo dõi phép này, vậy xin mấy anh chị cho mình cách nào có thể giúp mình xử lý được vấn đề.
Xin cảm ơn và chờ kết quả mấy anh chị.
 
Upvote 0
=if(today()>date(2008,3,31),NgayNP=0,NgayNP)
 
Upvote 0
Đây là ví dụ.
Vì phép 2007, 2008 của các tháng khác nhau là khác nhau.
Mình xin pst file này mong các anh chị sư huynh tỉ đệ mụi xem và sửa thêm. Thanks
 

File đính kèm

Lần chỉnh sửa cuối:
Upvote 0
Xin Hỏi

mình mò hoài mà không biết truy suất dữ liệu từ sheet "Quyuoc" qua sheet "Add_NV" bằng cách nào.
Tạo các nút fillter trên sheet "Add_NV" bằng cách nào?
các sư huynh chỉ giáo nhé.

hihifhihifhiff
 
Upvote 0
cho mình hỏi, nếu muốn gõ ngày đầu của 1 tháng và ngày cuối của 1 tháng ta gõ công thức như thế nào? ( không gõ : 1/../.. hay 30 hoặc 31/../...)
 
Upvote 0
cho mình hỏi, nếu muốn gõ ngày đầu của 1 tháng và ngày cuối của 1 tháng ta gõ công thức như thế nào? ( không gõ : 1/../.. hay 30 hoặc 31/../...)
không biết có đúng ý bạn không?
giả sử A1 là ô chứa tháng, B1 là ô chứa năm
ngày đầu tiên của tháng: A2=date($B$1,$A$1,1)
ngày cuối cùng của tháng: A2=date($B$1,$A$1+1,0)
 
Upvote 0
cám ơn bạn, thật ra mình muốn gõ giống như kiểu hàm now(), nhưng ở đây muốn gõ ngày đầu tháng và kết thúc tháng thôi. nếu ko có thì mình chịu vậy.
 
Upvote 0
Xin giới thiệu một cách viết khác của hàm chấm công

Xin giới thiệu cách viết khác của hàm chấm công.

Tôi xin giới thiệu các bạn một hàm chấm công được áp dụng với Module split của cpearson .

Mục đích của hàm giống như trong thread #1 đã giới thiệu. Hàm sẽ tách số trong một chuổi ra.
Xin xem file đính kèm để hiểu rõ hơn về cách sử dụng.

Mã:
Function ChamCong(vInput As Variant, sFunction As String) As Variant

    Const c_Delim_1 = ";"
    Const c_Delim_2 = ":"
    Dim arr1() As String, arr2() As String
    Dim i As Long, j As Long
    Dim sngTemp As Single
    Dim rngCell As Range
    
    On Error GoTo ChamCong_Error
    'Kiem tra bien Range dua vao
    If TypeOf vInput Is Range Then
        For Each rngCell In vInput
            If Len(rngCell.Value) > 0 Then
                arr1 = SplitMultiDelims(rngCell.Value, c_Delim_1)
                If IsArrayAllocated(arr1) Then

                    For j = LBound(arr1) To UBound(arr1)
                        arr2 = SplitMultiDelims(arr1(j), c_Delim_2)
                        If arr2(1) = sFunction Then
                            sngTemp = sngTemp + CSng(arr2(2))
                        End If
                    Next j
                End If
            End If
        Next
        ChamCong = sngTemp
    Else
        GoTo ChamCong_Error
    End If
ChamCong_Exit:
    Exit Function

ChamCong_Error:
    ChamCong = "#Error"
    Resume ChamCong_Exit

End Function

Lê Văn Duyệt
 

File đính kèm

Lần chỉnh sửa cuối:
Upvote 0
Sử dụng Update list

Đây là ví dụ.
Vì phép 2007, 2008 của các tháng khác nhau là khác nhau.
Mình xin pst file này mong các anh chị sư huynh tỉ đệ mụi xem và sửa thêm. Thanks
Sao mình bấm vào update list, thêm nhân viên hoặc update phép mà ko được vậy? phải làm thế nào bạn giúp tôi với
 
Upvote 0
Cám ơn anh Lê Văn Duyệt về đoạn code về tổng hợp ngày công trong bảng chấm công, nó rất phù hợp với công việc của tôi.
Nhưng có điều tôi muôn sthay các ký hiện chấm công để thuận tiện như:
Bỏ dấu ":", ví dụ 12;2d1;4t1, được hiểu là: có 12 giờ làm việc, trong đó 2 giờ làm đêm có phụ cấp 30% (ngoài ra còn có mức 35% là d2), 4 giờ làm thêm mức 150% (ngoài ra có mức 200% là t2).
Làm sao chỉnh đoạn code của anh làm được điều này.
Tôi đã làm thử mà không được, anh xem file đính kèm để chỉ giúp.
Cám ơn nhiều.
 

File đính kèm

Upvote 0
Web KT

Bài viết mới nhất

Back
Top Bottom