|
楼主 |
发表于 2009-9-7 08:26
|
显示全部楼层
第11部分 其他应用
技巧198 职工考勤系统
步骤5,将Sheet3工作表名称重命名为“考勤统计”,设置成如图所示的格式,用来汇总部门考勤考核数据及打印“考勤统计”表。
步骤6,在VBE窗口中单击菜单“插入”→“插入窗体”,在窗体中添加一个框架控件及两个按钮控件,在框架控件中添加四个标签控件、一个组合框控件、一个文本框控件和一个SpinButton控件,如图所示。
双击窗体,在打开的代码窗口写入下面的代码:- #001 Private Sub UserForm_Initialize()
- #002 Dim i As Integer
- #003 For i = 4 To Sheet1.Range("A65536").End(xlUp).Row
- #004 ComboBox1.AddItem Sheet1.Cells(i, 1)
- #005 Next
- #006 ComboBox1.ListIndex = 0
- #007 Label4 = Sheet1.Range("B1")
- #008 SpinButton1.Value = Month(Date)
- #009 TextBox1.Text = Year(Date) & "年" & Month(Date) & "月"
- #010 End Sub
复制代码 代码解析:
部门考勤窗体的初始化事件,为组合控件添加部门名称,为文本框控件添加考勤月份。
双击窗体上的SpinButton控件,在打开的代码窗口写入下面的代码:- #001 Private Sub SpinButton1_Change()
- #002 With SpinButton1
- #003 Select Case .Value
- #004 Case 1 To 12
- #005 TextBox1 = Left(TextBox1, 4) & "年" & .Value & "月"
- #006 Case Is > 12
- #007 .Value = 1
- #008 TextBox1 = Left(TextBox1, 4) + 1 & "年" & .Value & "月"
- #009 Case Is < 1
- #010 .Value = 12
- #011 TextBox1 = Left(TextBox1, 4) - 1 & "年" & .Value & "月"
- #012 End Select
- #013 End With
- #014 End Sub
复制代码 代码解析:
SpinButton控件的Change事件,调节文本框控件中的考勤月份。
双击窗体上的“确定”按钮,在打开的代码窗口写入下面的代码:- #001 Private Sub CommandButton1_Click()
- #002 Dim s As Integer
- #003 Dim Sh As Worksheet
- #004 Dim arr As Variant
- #005 Dim arrName As Variant
- #006 Dim i As Integer
- #007 Dim i1 As Integer
- #008 Dim j As Integer
- #009 Dim j1 As Integer
- #010 Dim r As Integer
- #011 Dim c As Integer
- #012 Dim str As String
- #013 Dim d As Integer
- #014 Application.ScreenUpdating = False
- #015 Application.DisplayAlerts = False
- #016 For s = Worksheets.Count To 4 Step -1
- #017 Worksheets(s).Delete
- #018 Next
- #019 Application.DisplayAlerts = True
- #020 With Sheet1
- #021 For i = 4 To .Range("A65536").End(xlUp).Row
- #022 If ComboBox1.Text = .Cells(i, 1) And .Cells(i, 4) = "" Then
- #023 MsgBox "请增加部门人员!", 64, "提示"
- #024 Unload Me
- #025 Exit Sub
- #026 End If
- #027 Next
- #028 End With
- #029 With Sheet3
- #030 .Unprotect
- #031 r = .Range("B65536").End(xlUp).Row
- #032 If r >= 50 Then
- #033 .Rows("50:" & r).Delete Shift:=xlUp
- #034 End If
- #035 .Range("B1") = Sheet1.Range("B1") & "出缺勤统计表"
- #036 .Range("C2") = ComboBox1.Text
- #037 .Range("O2") = TextBox1.Text
- #038 For i = 4 To Sheet1.Range("A65536").End(xlUp).Row
- #039 If ComboBox1.Text = Sheet1.Cells(i, 1) Then
- #040 r = Sheet1.Cells(i, 255).End(xlToLeft).Column
- #041 .Range("C30") = Sheet1.Cells(i, 2)
- #042 .Range("O30") = Sheet1.Cells(i, 3)
- #043 For c = 4 To r
- #044 .Cells(c + 46, 2) = Sheet1.Cells(i, c)
- #045 Next
- #046 End If
- #047 Next
- #048 r = .Range("B65536").End(xlUp).Row
- #049 .Range("I50:I" & r).FormulaR1C1 = "=SUM(RC[-4]:RC[-1])"
- #050 .Range("M50:M" & r).FormulaR1C1 = "=SUM(RC[-3]:RC[-1])"
- #051 .Range("B50:O" & r).Borders.LineStyle = xlContinuous
- #052 .Range("C50:C" & r).Locked = False
- #053 .Range("E50:H" & r).Locked = False
- #054 .Range("J50:L" & r).Locked = False
- #055 .ScrollArea = ""
- #056 Application.Goto Reference:=.Range("A50"), Scroll:=True
- #057 .ScrollArea = "A50:O" & r
- #058 .Protect
- #059 .EnableSelection = xlUnlockedCells
- #060 End With
- #061 For i = 4 To Sheet1.Range("A65536").End(xlUp).Row
- #062 If ComboBox1.Text = Sheet1.Cells(i, 1) Then
- #063 c = i
- #064 For j = 4 To Sheet1.Cells(i, 255).End(xlToLeft).Column
- #065 str = str & Sheet1.Cells(i, j) & ","
- #066 Next
- #067 End If
- #068 Next
- #069 arrName = Split(Left(str, (Len(str) - 1)), ",")
- #070 For i1 = 0 To UBound(arrName)
- #071 Set Sh = Worksheets.Add(after:=Worksheets(Worksheets.Count))
- #072 With Sh
- #073 .Name = arrName(i1)
- #074 arr = Array(1.75, 4.5, 3, 3, 3, 3, 45, 9, 1.75)
- #075 For i = LBound(arr) To UBound(arr)
- #076 .Columns(i + 1).ColumnWidth = arr(i)
- #077 Next
- #078 arr = Array(33, 24, 18)
- #079 For i = LBound(arr) To UBound(arr)
- #080 .Rows(i + 1).RowHeight = arr(i)
- #081 Next
- #082 .Rows("4:36").RowHeight = 16.5
- #083 .Rows(37).RowHeight = 30
- #084 .Range("B1:H1,B2:H2,C4:D4,E4:F4,B4:B5,G4:G5,H4:H5,B37:G37").Merge
- #085 With .Range("B4:H37")
- #086 .Borders.LineStyle = xlContinuous
- #087 .BorderAround xlDouble
- #088 End With
- #089 With .Range("B1")
- #090 .HorizontalAlignment = xlCenter
- #091 .Value = Sheet1.Range("B1") & "人员考核记录表"
- #092 .Font.Name = "黑体"
- #093 .Font.Size = 16
- #094 .Font.Bold = True
- #095 End With
- #096 With .Range("B2")
- #097 .HorizontalAlignment = xlCenter
- #098 .Value = TextBox1.Text
- #099 .Font.Bold = True
- #100 End With
- #101 With .Range("B3")
- #102 .Value = "姓名:" & arrName(i1)
- #103 .HorizontalAlignment = xlLeft
- #104 .Font.Size = 10
- #105 End With
- #106 With .Range("B4:H37")
- #107 .HorizontalAlignment = xlCenter
- #108 .Font.Size = 10
- #109 End With
- #110 .Range("B4").Value = "日" & Chr(10) & "期"
- #111 .Range("C4").Value = "上午"
- #112 .Range("E4").Value = "下午"
- #113 .Range("G4").Value = "工作内容(加班情况或外出记录)"
- #114 .Range("H4").Value = "备注"
- #115 .Range("C5,E5").Value = "到"
- #116 .Range("D5,F5").Value = "缺"
- #117 .Range("B37").Value = "本月考核得分总计"
- #118 With .Range("B38")
- #119 .Value = "部门负责人:" & Sheet1.Cells(c, 2)
- #120 .HorizontalAlignment = xlLeft
- #121 .Font.Size = 10
- #122 End With
- #123 With .Range("H38")
- #124 .Value = "考勤员:" & Sheet1.Cells(c, 3)
- #125 .Font.Size = 10
- #126 .HorizontalAlignment = xlRight
- #127 End With
- #128 Select Case Val(Sheet1.Cells(2, 2))
- #129 Case 26 To 28
- #130 If Month(TextBox1.Text & "1日") <> 1 Then
- #131 .Cells(6, 2) = Year(TextBox1.Text & "1日") & "-" & Month(DateAdd("m", -1, TextBox1.Text & "1日")) & "-" & Val(Sheet1.Cells(2, 2))
- #132 Else
- #133 .Cells(6, 2) = (Year(TextBox1.Text & "1日") - 1) & "-" & Month(DateAdd("m", -1, TextBox1.Text & "1日")) & "-" & Val(Sheet1.Cells(2, 2))
- #134 End If
- #135 Case 1 To 5
- #136 .Cells(6, 2) = Year(TextBox1.Text & "1日") & "-" & Month(TextBox1.Text & "1日") & "-" & Val(Sheet1.Cells(2, 2))
- #137 End Select
- #138 For i = 1 To 30
- #139 Cells(i + 6, 2) = .Cells(6, 2) + i
- #140 If .Cells(i + 6, 2).Value = DateAdd("m", 1, .Cells(6, 2)) - 1 Then Exit For
- #141 Next
- #142 .Range("B6:B36").NumberFormatLocal = "d"
- #143 For i = 6 To 36
- #144 If .Cells(i, 2) <> "" Then
- #145 Select Case DatePart("w", .Cells(i, 2))
- #146 Case 7, 1
- #147 .Cells(i, 7) = "休 息"
- #148 Case 2, 3, 4, 5, 6
- #149 .Cells(i, 3) = "√"
- #150 .Cells(i, 5) = "√"
- #151 .Cells(i, 7) = "上 班"
- #152 d = d + 1
- #153 End Select
- #154 Select Case Mid(Cells(i, 2), 6, Len(Cells(i, 2)) - 5)
- #155 Case "01-01"
- #156 .Cells(i, 3) = ""
- #157 .Cells(i, 5) = ""
- #158 .Cells(i, 7) = "元 旦"
- #159 d = d - 1
- #160 Case "05-01"
- #161 .Cells(i, 3) = ""
- #162 .Cells(i, 5) = ""
- #163 .Cells(i, 7) = "五一节"
- #164 d = d - 1
- #165 Case "10-01", "10-02", "10-03"
- #166 .Cells(i, 3) = ""
- #167 .Cells(i, 5) = ""
- #168 .Cells(i, 7) = "国庆节"
- #169 d = d - 1
- #170 End Select
- #171 Select Case Mid(NongLi(Cells(i, 2)), 9, 5)
- #172 Case "正月初一", "正月初二", "正月初三"
- #173 .Cells(i, 3) = ""
- #174 .Cells(i, 5) = ""
- #175 .Cells(i, 7) = "春 节"
- #176 d = d - 1
- #177 Case "四月初四"
- #178 .Cells(i, 3) = ""
- #179 .Cells(i, 5) = ""
- #180 .Cells(i, 7) = "清明节"
- #181 d = d - 1
- #182 Case "五月初五"
- #183 .Cells(i, 3) = ""
- #184 .Cells(i, 5) = ""
- #185 .Cells(i, 7) = "端午节"
- #186 d = d - 1
- #187 Case "八月十五"
- #188 .Cells(i, 3) = ""
- #189 .Cells(i, 5) = ""
- #190 .Cells(i, 7) = "中秋节"
- #191 d = d - 1
- #192 End Select
- #193 End If
- #194 Next
- #195 .Range("E3") = d
- #196 d = 0
- #197 .Range("H3").FormulaR1C1 = "=(COUNTA(R[3]C[-5]:R[33]C[-5],R[3]C[-3]:R[33]C[-3],""√"""""")-1)/2"
- #198 .Range("H37").FormulaR1C1 = "=ROUND(IF(R[-34]C/R[-34]C[-3]*100>100,100,R[-34]C/R[-34]C[-3]*100),0)"
- #199 .Range("E3,H3").Font.ColorIndex = 2
- #200 .Range("C6:G36").Locked = False
- #201 .Rows("6").Select
- #202 .PageSetup.CenterHorizontally = True
- #203 .DisplayAutomaticPageBreaks = False
- #204 With ActiveWindow
- #205 .DisplayGridlines = False
- #206 .DisplayHeadings = False
- #207 .DisplayOutline = False
- #208 .FreezePanes = True
- #209 .DisplayGridlines = False
- #210 End With
- #211 .ScrollArea = "B1:O42"
- #212 .Range("G6").Select
- #213 .Protect
- #214 .EnableSelection = xlUnlockedCells
- #215 End With
- #216 Next
- #217 Sheets("考勤统计").Select
- #218 Unload Me
- #219 Application.ScreenUpdating = True
- #220 End Sub
复制代码 代码解析:
部门考勤窗体中“确定”按钮的单击事件,将所考勤部门的人员姓名写入到“考勤统计”表的姓名列中并在工作簿中该部门所有人员的个人考核表。
第15行到第19行代码,删除工作簿中原有的个人考核表。
第20行到第28行代码,判断所要考勤的部门是否已添加了部门人员。
第32行到第34行代码,删除“考勤统计”表中原有的统计数据,因为“考勤统计”表中B1:O30的表格是打印表格用的,统计数据是保存在B50以下单元格中,所以考勤前需要删除。
第35行代码,将单位名称写入到“考勤统计”表的B1单元格。
第36行代码,将考勤部门写入到“考勤统计”表的C2单元格。
第4行代码,将考勤月份写入到“考勤统计”表的O2单元格。
第41行代码,将部门负责人写入到“考勤统计”表的C30单元格。
第42行代码,将考勤员写入到“考勤统计”表的O30单元格。
第43行到第45行代码,将“资料”表中所保存的该部门人员姓名写入“考勤统计”表的B50及B50往下单元格中。
第49、50行代码,在“考勤统计”表的I50、M50及以下单元格中写入合计公式并将单元格属性设置为锁定。
第51行代码,将“考勤统计”表的B50至O列的最后一行单元格添加边框线。
第52行到第54行代码,取消“考勤统计”表中需要编辑单元格的锁定属性。
第55行到第57行代码,将“考勤统计”表的可选择区域设置为B50至O列的最后一行单元格并使用Goto方法选择B50单元格。
第58、59行代码,保护“考勤统计”表,使之只能选择未锁定的单元格。
写入考勤数据的“考勤统计”表如图所示。
第61行到第69代码,将该部门保存在“资料”表中的人员姓名赋给数组arrName。
第70、71行代码,根据数组arrName保存的人员姓名依次在工作簿中添加个人考核表。
第73行代码,将添加的工作表以人员姓名重新命名。
第74行到第83行代码,设置个人考核表的行高、列宽。
第84行代码,合并个人考核表中的单元格。
第85行到第88行代码,设置个人考核表的边框线。
第59行到第127行代码,在个人考核表写入表格内容并设置格式。
第128行到第142行代码,在个人考核表的日期栏中根据考勤月份及考勤周期写入考勤日期并设置自定义格式。
第145行到第153行代码,使用DatePart函数判断考勤日期的星期并在个人考核表的“到”栏和“工作内容”栏中写入系统默认的内容,其中第152行代码,将应出勤天数赋给变量d。
第154行到第170行代码,判断考勤日期是否是“元旦”、“五一节”及“国庆节”,如果是则去除个人考核表的“到”栏中的应出勤标志,在“工作内容”栏中写入节假日名称并将应出勤天数减去放假天数。
第171行到第192行代码,判断考勤日期是否是“春节”、“清明节”、“端午节”及“中秋节”,如果是则去除个人考核表的“到”栏中的应出勤标志,在“工作内容”栏中写入节假日名称并将应出勤天数减去放假天数。
判断考勤日期的农历日期需使用自定义函数,在VBE窗口中单击菜单“插入”→“模块”,在打开的代码窗口写入下面的代码:- #001 Public Function NongLi(Optional XX_DATE As Date)
- #002 Dim MonthAdd(11), NongliData(99), TianGan(9), DiZhi(11), ShuXiang(11), DayName(30), MonName(12)
- #003 Dim curTime, curYear, curMonth, curDay
- #004 Dim GongliStr, NongliStr, NongliDayStr
- #005 Dim i, m, n, k, isEnd, bit, TheDate
- #006 代码略,详见附件
- #007 NongliStr = "农历" & TianGan(((curYear - 4) Mod 60) Mod 10) & DiZhi(((curYear - 4) Mod 60) Mod 12) & "年"
- #008 NongliStr = NongliStr & "(" & ShuXiang(((curYear - 4) Mod 60) Mod 12) & ")"
- #009 If (curMonth < 1) Then
- #010 NongliDayStr = "闰" & MonName(-1 * curMonth)
- #011 Else
- #012 NongliDayStr = MonName(curMonth)
- #013 End If
- #014 NongliDayStr = NongliDayStr & "月"
- #015 NongliDayStr = NongliDayStr & DayName(curDay)
- #016 NongLi = NongliStr & NongliDayStr
- #017 End Function
复制代码 自定义NongLi函数根据日期生成农历天干、地支、属相等,来自网络,未做任何修改。其中第171行代码使用Mid函数取得农历日期。
第195行代码,将统计出的应出勤天数写入到个人考核表的E3单元格。
第197行代码,在个人考核表的H3单元格中写入统计实际出勤天数的公式。
第198行代码,在个人考核表的H36单元格中写入计算考核得分的公式。
第199行到第216行代码,设置个人考核表的页面格式及工作表保护。
添加好的个人考核表如图所示。
在实际应用时,系统统计出的出勤数据与实际出勤数据可能有出入,为了方便修改数据,在VBE中双击ThisWorkbook写入下面的代码:- #001 Private Sub Workbook_SheetSelectionChange(ByVal Sh As Object, ByVal Target As Range)
- #002 If Sh.Index > 3 And Target.Count = 1 Then
- #003 If Sh.Range("B" & Target.Row) <> "" Then
- #004 If Not Application.Intersect(Target, Union(Sh.Range("C6:C36"), Sh.Range("E6:E36"))) Is Nothing Then
- #005 Target = "√"
- #006 Target.Offset(, 1) = ""
- #007 End If
- #008 If Not Application.Intersect(Target, Union(Sh.Range("D6:D36"), Sh.Range("F6:F36"))) Is Nothing Then
- #009 Target = "△"
- #010 Target.Offset(, -1) = ""
- #011 End If
- #012 End If
- #013 End If
- #014 End Sub
复制代码 代码解析:
工作簿的SheetSelectionChange事件,选择个人考核表中的“到”或“缺”栏中的单元格时,自动在单元格中写入出缺勤标志。- #001 Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range)
- #002 Dim rng As Range
- #003 If Sh.Index > 3 And Target.Count = 1 Then
- #004 If Sh.Range("B" & Target.Row) <> "" Then
- #005 If Not Application.Intersect(Target, Sh.Range("C6:F36")) Is Nothing Then
- #006 Select Case Target
- #007 Case "√"
- #008 Sh.Range("G" & Target.Row) = "上 班"
- #009 Case "△"
- #010 Sh.Range("G" & Target.Row) = "缺 勤"
- #011 End Select
- #012 End If
- #013 End If
- #014 End If
- #015 End Sub
复制代码 代码解析:
工作簿的SheetChange事件,根据个人考核表中的“到”或“缺”栏中写入出缺勤标志自动调整工作内容栏中的工作内容。 |
|