摘 要 本文介绍了在Word中使用“宏”技术实现对成绩登记表的自动计算,实现各种格式要求的方法。
关键字 宏,VBA,成绩登记表,计算
一、前言
成绩登记表是高校中每个任课老师在学期末都要统计填写的。通常的做法是先根据总成绩的计算要求,比如总成绩由平时成绩、实验成绩、期末考试成绩按教学大纲规定比例进行合计,利用Excel电子表格的计算功能,计算出总成绩。再将平时成绩、实验成绩、期末考试成绩等各项成绩粘贴到Word的成绩登记表中。这是一项繁琐费时的工作。特别当成绩登记表还有一些特殊处理要求:如考试课成绩以百分计,考查课成绩以“优”、“良”、“中”等标记;低于60分的成绩加方框;考试成绩低于某一分数的加阴影;统计各分数段成绩分布等处理时;虽然这些处理在Excel或Word中通过能通过一系列操作完成,但这些操作一则繁琐、费时,易出错;二则有些操作还是比较复杂,对于非计算机专业的老师要求过高,不易掌握。为此笔者在我校成绩登记表模板的基础上,使用“宏”技术实现了成绩登记表的成绩自动计算及其他各项处理要求。
二、处理要求
我校成绩登记表Word模板如图1和图2所示。
图1 成绩登记部分
图2 成绩分布及总成绩构成比例
根据我校成绩登记表的填写要求,自动处理应具备的功能为:
1. 根据课程性质,输入学生成绩。可以输入分数、也可以输入等第;
2. 根据课程性质,计算学生期末总成绩。如果是考试课程,期末成绩为分数,如果是考查,则期末成绩是等级;
3. 对于各项不及格成绩,成绩上加方框;考试课程期末成绩小于45分,总成绩即为期末成绩,不再考虑其他成绩;并加上阴影;
4. 统计成绩分布;
5. 程序应放宽输入要求,对输入数据进行必要的检查,即程序应具有一定的健壮性,操作方便。
三、设计方案
设计方案是在基本不改变原来成绩登记表原有模板的基础上,利用Word提供的 “宏”,使用VBA,设计相应的程序,完成上述5项功能。
1.为方便操作,建立一自定义工具栏。建立过程如下:
使用Word “视图”菜单中的“工具栏”子菜单,自定义成绩统计工具栏并生成“成绩统计”和“帮助”2个按钮,在“工具”菜单中的“宏”子菜单中确定2个按钮对应的2个宏名,即宏的过程名。本例中宏名分别为calculate和help,并确定将宏保存在本文档中。这样每次打开成绩登记表,该工具栏自行打开(如图3所示)。
图3 自定义成绩统计工具栏
2.在成绩登记表上增加2个单选按钮,将其caption属性设置为“考试”、“考查”,用来确定课程性质。
3.设计calculate宏,calculate的主要功能如下:
确定课程性质;检查总成绩构成比例是否为100;初始化统计过程中使用的数组变量,表格字体字号,对齐方式等;对表中每个学生的成绩,调用自定义过程Score_Statistic,逐个统计并作相应处理;统计成绩分布。由于成绩分布百分比要求保留一位小数,因此需要对成绩分布的百分比作处理,保证各百分比之和为100。
4.设计自定义过程Score_Statistic宏,Score_Statistic的主要功能如下:
从表格的单元格中取出学生的3项成绩调用Convert_Int函数进行数据转换;根据课程性质和总成绩构成的百分比计算期末总成绩;对学生的4项成绩进行格式处理:低于60分加框,考试课程期末总成绩低于45分加阴影、考查课总成绩以5级等第表示、缺考的成绩不作处理;根据期末总成绩进行各分数段人数累计;统计期末总成绩低于45分的人数;Score_Statistic的参数为为待处理的单元格的行列号。
四、操作过程
进入Word打开待处理的成绩登记表,确定考试性质、输入学生各项成绩的分数或等第、输入总成绩构成比例后,鼠标左击图3中的“成绩统计”按钮,即可进行成绩自动处理。
经过处理以后的成绩表如图4、图5和图6所示。
图4 处理以后的考试课程成绩表
图5 处理以后的考查课程成绩表
图6 成绩分布
五、源代码
`alculate宏代码
Private Sub calculate()
Dim number_of_stu As Integer, i As Integer, j As Integer
Dim student_id As String
Dim fraction As Single
exam_or_check = ThisDocument.OptionButton1.Value
proportion(1) = Val(ThisDocument.Tables(1).Cell(33, 2).Range.Text)
proportion(2) = Val(ThisDocument.Tables(1).Cell(33, 4).Range.Text)
proportion(3) = Val(ThisDocument.Tables(1).Cell(33, 6).Range.Text)
If proportion(1) + proportion(2) + proportion(3) <> 100 Then
MsgBox "平时成绩:实验成绩:期末成绩三项之和不等于100", vbOKOnly, message_title
Exit Sub
End If
number_of_stu = 0
For i = 1 To 7: grade_proportion(1, i) = 0: grade_proportion(2, i) = 0: Next '成绩分布初始化
For i = 1 To 25
ThisDocument.Tables(1).Cell(i + 1, 4).Range.Font.Size = 9 '设置字号
ThisDocument.Tables(1).Cell(i + 1, 5).Range.Font.Size = 9
ThisDocument.Tables(1).Cell(i + 1, 6).Range.Font.Size = 9
ThisDocument.Tables(1).Cell(i + 1, 7).Range.Font.Size = 9
ThisDocument.Tables(1).Cell(i + 1, 4).Range.ParagraphFormat.Alignment = wdAlignParagraphCenter
'设置对齐方式
ThisDocument.Tables(1).Cell(i + 1, 5).Range.ParagraphFormat.Alignment = wdAlignParagraphCenter
ThisDocument.Tables(1).Cell(i + 1, 6).Range.ParagraphFormat.Alignment = wdAlignParagraphCenter
ThisDocument.Tables(1).Cell(i + 1, 7).Range.ParagraphFormat.Alignment = wdAlignParagraphCenter
student_id = Trim(ThisDocument.Tables(1).Cell(i + 1, 2).Range.Text) '取学号
If Len(student_id) > 2 Then '计算成绩表左侧成绩
number_of_stu = number_of_stu + 1
Call Score_Statistic(i, 4)
End If
ThisDocument.Tables(1).Cell(i + 1, 11).Range.Font.Size = 9
ThisDocument.Tables(1).Cell(i + 1, 12).Range.Font.Size = 9
ThisDocument.Tables(1).Cell(i + 1, 13).Range.Font.Size = 9
ThisDocument.Tables(1).Cell(i + 1, 14).Range.Font.Size = 9
ThisDocument.Tables(1).Cell(i + 1, 11).Range.ParagraphFormat.Alignment = wdAlignParagraphCenter
ThisDocument.Tables(1).Cell(i + 1, 12).Range.ParagraphFormat.Alignment = wdAlignParagraphCenter
ThisDocument.Tables(1).Cell(i + 1, 13).Range.ParagraphFormat.Alignment = wdAlignParagraphCenter
ThisDocument.Tables(1).Cell(i + 1, 14).Range.ParagraphFormat.Alignment = wdAlignParagraphCenter
student_id = Trim(ThisDocument.Tables(1).Cell(i + 1, 9).Range.Text) '取学号
If Len(student_id) > 2 Then '计算成绩表右侧成绩
number_of_stu = number_of_stu + 1
Call Score_Statistic(i, 11)
End If
Next i
If number_of_stu = 0 Then MsgBox "没有学生成绩数据", vbExclamation + vbOKOnly, message_title: Exit Sub
'计算成绩分布
fraction = 100
For i = 1 To 7
If grade_proportion(1, i) > 0# Then
grade_proportion(2, i) = Round(grade_proportion(1, i) / number_of_stu * 100, 1)
If i < 7 Then fraction = fraction - grade_proportion(2, i): j = i '考试课程卷面成绩<45
`不用调整百分比
Else
grade_proportion(2, i) = 0
End If
Next
'百分比调整为100%
If Abs(fraction) >= 0.05 Then grade_proportion(2, j) = Round(grade_proportion(2, j) + fraction, 1)
For i = 1 To 7
ThisDocument.Tables(1).Cell(31, i + 1).Range.Text = grade_proportion(1, i)
ThisDocument.Tables(1).Cell(32, i + 1).Range.Text = grade_proportion(2, i)
Next
MsgBox "成绩登记完毕,请检查", vbOKOnly, message_title
End Sub
'Score_Statistic自定义过程代码
Private Sub Score_Statistic(ByVal row As Integer, ByVal column As Integer)
Dim grade(3) As Single, total As Single
With ThisDocument.Tables.Item(1)
'调用自定义函数Convert_Int进行字符型数据到数值型数据转换
If Len(Trim(.Cell(row + 1, column + 2).Range.Text)) = 2 Then '缺考
.Cell(row + 1, column + 3).Range.Text = "缺考"
grade(1) = Convert_Int(.Cell(row + 1, column).Range.Text) '平时成绩
grade(2) = Convert_Int(.Cell(row + 1, column + 1).Range.Text) '实验成绩
grade(3) = -1
total = -1
Else '不缺考
grade(1) = Convert_Int(.Cell(row + 1, column).Range.Text) '平时成绩
grade(2) = Convert_Int(.Cell(row + 1, column + 1).Range.Text) '实验成绩
grade(3) = Convert_Int(.Cell(row + 1, column + 2).Range.Text) '期末成绩
'期末考试成绩小于45分,总成绩为期末考试成绩
If exam_or_check Then '考试
total = IIf(grade(3) < 45, grade(3), Round((grade(1) * proportion(1) + grade(2) * proportion(2) + grade(3) * proportion(3)) / 100, 0))
.Cell(row + 1, column + 3).Range.Text = total
Else '考查
total = Round((grade(1) * proportion(1) + grade(2) * proportion(2) + grade(3) * proportion(3)) / 100, 0)
.Cell(row + 1, column + 3).Range.Text = IIf(total >= 90, "优", IIf(total >= 80, "良", IIf(total >= 70, "中", IIf(total >= 60, "及格", IIf(total >= 0, "不及格", "")))))
End If
End If
'各项成绩小于60分加框
.Cell(row + 1, column).Range.Font.Borders.Enable = IIf(grade(1) >= 0 And grade(1) < 60, True, False)
.Cell(row + 1, column + 1).Range.Font.Borders.Enable = IIf(grade(2) >= 0 And grade(2) < 60, True, False)
.Cell(row + 1, column + 2).Range.Font.Borders.Enable = IIf(grade(3) >= 0 And grade(3) < 60, True, False)
.Cell(row + 1, column + 3).Range.Font.Borders.Enable = IIf(total >= 0 And total < 60, True, False)
'期末考试成绩小于45分,加阴影
If exam_or_check Then
.Cell(row + 1, column + 3).Range.Shading.BackgroundPatternColor = IIf(grade(3) >= 0 And grade(3) < 45, wdColorGray20, wdColorWhite)
Else
.Cell(row + 1, column + 3).Range.Shading.BackgroundPatternColor = wdColorWhite
End If
'统计成绩分布
Select Case total
Case Is >= 90 '优秀
grade_proportion(1, 1) = grade_proportion(1, 1) + 1
Case Is >= 80 '良好
grade_proportion(1, 2) = grade_proportion(1, 2) + 1
Case Is >= 70 '中等
grade_proportion(1, 3) = grade_proportion(1, 3) + 1
Case Is >= 60 '及格
grade_proportion(1, 4) = grade_proportion(1, 4) + 1
Case Is >= 0 '不及格
grade_proportion(1, 5) = grade_proportion(1, 5) + 1
Case Else '缺考
grade_proportion(1, 6) = grade_proportion(1, 6) + 1
End Select
'统计考试课程卷面成绩小于45分
If exam_or_check Then
If grade(3) >= 0 And grade(3) < 45 Then
grade_proportion(1, 7) = grade_proportion(1, 7) + 1
End If
End If
End With
End Sub
自定义函数Convert_Int代码:
Private Function Convert_Int(ByRef Txt As String) As Integer
Dim Score As String * 1
If Asc(Txt) > 0 Then '数字
Convert_Int = Val(Txt)
Else
Score = Txt
Convert_Int = IIf(Score = "优", 95, IIf(Score = "良", 85, IIf(Score = "中", 75, IIf(Score = "及", 65, 55))))
End If
End Function
`全局变量声明
Option Base 1
Option Explicit
Dim exam_or_check As Boolean
Dim grade_proportion(2, 7) As Single
Dim proportion(3) As Integer
Private Const Message_Title = "江苏技术师范学院学生成绩登记系统"
|