娄青
(浙江省宁海中学,浙江宁波 315600)
考试在普通高中学校教学过程中有着极其重要的地位,它能检测学生知识掌握程度,能检查教师教学情况,能衡量一所学校办学质量,因此学校常常举行各种月考和联考。在一所普通高中学校里,往往有三个年级和文理分科情况,一次考试过程中学生考场和座位的安排就是一项任务繁重的工作,一般的考试分析系统没有考生座位安排模块,主管考试工作的教师就经常进行学生试场手工安排的重复性工作。微软的Excel软件为大家所熟悉和掌握,教师都非常喜欢用它来处理各种教学事务,经过笔者研究,发现Excel软件工作表的单元格排列方式跟考场座位安排有相似之处,都比较工整有序有规律,为此有了利用Excel软件和VBA技术开发普通高中考试排座系统的想法,并进行尝试和实现。
由于高中存在三个年级和文理分科的情况,考试排座就显得非常复杂,我们以高三理科排座为例讲述普通高中考试排座系统,其余排座方法与此差不多,不再重复。该系统由四个程序模块和五个Excel工作表组成,“高三理科”工作表存放高三理科学生名单,“高三座位”工作表存放各试场座位情况,“试场安排”工作表存放试场人数与各排人数,“班级情况”工作表存放班级数和各班学生人数,“试场分布”工作表存放试场号与试场位置。下面就四个程序模块代码加以详细说明。
在该模块代码中,程序取得“班级情况”工作表上的数据,如图1所示,赋予并初始化各系统参数,为接下来的排座做好准备,其程序代码如下(附有程序注解):
图1 “班级情况”工作表
Option Explicit
Public Gao3LiBanShu As Integer'高三理科班级数
Public Gao3Li(20)As Integer'高三理科各班人数
Public Gao3Row As Integer '工作表有效行数
Public ShiChangHao As Integer '试场号
Public ZongShiChang As Integer'总试场数
Public ShiChangShu As Integer'试场满员的试场数
Public YuShu As Integer'余数(未满员试场的学生人数)
Sub Init()
Dim i As Integer
Gao3LiBanShu=Worksheets("班级情况").Cells(1,4).Value'取得高三理科班级数
For i=1 To Gao3LiBanShu
Gao3Li(i)=Worksheets("班级情况").Cells(2+i,4).Value'取得高三理科各班人数
Next i
End Sub
图2 “高三理科”工作表,排座前
该模块进行随机方式的试场安排,在程序代码中,根据前面获得的初始化参数计算高三理科学生(如图2“高三理科”工作表所示)人数,并取得“试场安排”工作表的试场人数,如图3所示,由高三理科人数与试场人数计算得出满员试场数和未满员试场人数,对“高三理科”工作表选择的试场列区块产生随机数,同时对随机数进行排序,利用循环语句对满员的试场进行排座,最后对未满员的试场进行排座,如图4试场列所示,其程序代码如下:
图3 “试场安排”工作表,各排人数从右向左分别为第一排至第五排
图4 “高三理科”工作表,排座后
Sub PaiShiChang()'进行随机方式排试场
Dim i As Integer
Dim j As Integer
ShiChangHao=0 '初始化试场号,若前面有排过别的试场,ShiChangHao=ShiChangHao
Worksheets("高三理科").Activate'激活高三理科工作表
Gao3Row=1
For i=1 To Gao3LiBanShu
Gao3Row=Gao3Row+Gao3Li(i)'高三理科表最大有效行数
Next i
ShiChangShu=(Gao3Row-1)Worksheets("试场安排").Cells(4,2).Value'整除取得试场数
YuShu=(Gao3Row-1)Mod Worksheets("试场安排").
Cells(4,2).Value'整除余数为多少人
Cells(1,3).Value="试场"
Cells(Gao3Row,3).Select
Range(Selection,"c2").Select '选择试场列区块
Selection.Value="=rand()"'产生随机数
Cells(Gao3Row,3).Select
Range(Selection,"a2").Select
'排序,第一关键字:随机数,第二关键字:学号
Selection.Sort key1:=Columns(3),order1:=xlAs cending,key2:=Columns(1),order2:=xlAscending
For i=1 To ShiChangShu'进行满员的试场排座位
For j=1 ToWorksheets("试场安排").Cells(4,2).Value '进行一个试场的排座位
Cells(Worksheets("试场安排").Cells(4,2).Value*(i-1)+1+j,3).Value=i+ShiChangHao'赋予试场号
Next j
Next i
ZongShiChang=ShiChangShu
If YuShu<>0 Then'排最后一个试场
For j=1 To YuShu
Cells(ShiChangShu*Worksheets("试场安排").Cells(4,2).Value+1+j,3).Value=ShiChangShu+1+ShiChangHao
Next j
ZongShiChang=ZongShiChang+1'高三理科总试场数
End If
End Sub
图5 “试场分布”工作表
该模块进行各试场座位安排,在程序代码中,取得“试场安排”工作表的各排人数,即为各试场排座的各排人数,如图3所示。利用循环语句进行满员的试场排座,在循环体中首先取得“试场分布”工作表中的试场位置,如图5所示,再标示试场中每排的表头,按照试场的各排人数从“高三理科”工作表获取每排学生的学号与姓名,最后插入第几试场和分页符。对于未满员试场安排,根据未满员人数,分五种(因为试场是五排)情况进行排座。最后形成如图6所示的“高三座位”工作表。其程序代码如下:
图6 “高三座位”工作表,从右向左分别为第一排至第五排
Sub ZuoWeiBiao()'试场座位安排
Dim Num As Integer'高三理科表的行号
Dim ZuoWei As Integer'高三座位表的行号
Dim i As Integer'试场号变量
Dim j As Integer'试场排数变量
Dim k As Integer'试场每排的座位变量 (1-Row1~5)
Dim Row1 As Integer'第一排
Dim Row2 As Integer'第二排
Dim Row3 As Integer'第三排
Dim Row4 As Integer'第四排
Dim Row5 As Integer'第五排
Num=1
ZuoWei=1
Worksheets("高三座位").Activate'激活高三座位表
ZuoWei=ZuoWei+ShiChangHao*15
Row1=Worksheets("试场安排").Cells(4,7).Value
Row2=Worksheets("试场安排").Cells(4,6).Value
Row3=Worksheets("试场安排").Cells(4,5).Value
Row4=Worksheets("试场安排").Cells(4,4).Value
Row5=Worksheets("试场安排").Cells(4,3).Value
For i=1 To ShiChangShu'满员的试场排座位
Cells(ZuoWei,5).Value=Worksheets("试场分布").Cells(i+1+ShiChangHao,2).Value'试场位置,i+1+ShiChangHao是“试场分布”表中相应的行号
For j=1 To 5'试场中每排的表头
Cells(ZuoWei+12,j*2-1).Value="学号"
Cells(ZuoWei+12,j*2).Value="姓名"
Next j
For k=1 To Row1'第一大排
Cells(ZuoWei+12-k,9).Value=Worksheets("高三理科").Cells(Num+k,1).Value
Cells(ZuoWei+12-k,10).Value=Worksheets("高三理科").Cells(Num+k,2).Value
Next k
For k=1 To Row2'第二大排
Cells(ZuoWei+12-k,7).Value=Worksheets("高三理科").Cells(Num+Row1+k,1).Value
Cells(ZuoWei+12-k,8).Value=Worksheets("高三理科").Cells(Num+Row1+k,2).Value
Next k
… …(省略第三大排和第四大排情况)
… …
For k=1 To Row5'第五大排
Cells(ZuoWei+12-k,1).Value=Worksheets("高三理科").Cells(Num+Row1+Row2+Row3+Row4+k,1).Value
Cells(ZuoWei+12-k,2).Value=Worksheets("高三理科").Cells(Num+Row1+Row2+Row3+Row4+k,2).Value
Next k
Cells(ZuoWei+13,5).Value="讲台"
Cells(ZuoWei+14,5).Value="高三理科第"&i+ShiChangHao&"试场" '表明第几试场
Num=Num+Worksheets("试场安排").Cells(4,2).Value'准备指向高三理科表下一个试场
ZuoWei=ZuoWei+15'指向高三座位表下一个试场
Cells(ZuoWei,1).Activate
ActiveSheet.HPageBreaks.Add before:=ActiveCell'插入分页符
Next i'下一个试场
If YuShu<>0 Then'未满员试场安排
Cells(ZuoWei,5).Value=Worksheets("试场分布").Cells(ShiChangShu+1+1+ShiChangHao,2).Value
If YuShu<=Row1 Then '到第一大排止
Cells(ZuoWei+12,9).Value="学号"'第一大排的表头
Cells(ZuoWei+12,10).Value="姓名"
For k=1 To YuShu
Cells(ZuoWei+12-k,9).Value=Worksheets("高三理科").Cells(Num+k,1).Value
Cells(ZuoWei+12-k,10).Value=Worksheets("高三理科").Cells(Num+k,2).Value
Next k
End If
If YuShu>Row1 And YuShu<=Row1+Row2 Then '到第二大排止
For j=1 To 2'第一大排到第二大排的表头
Cells(ZuoWei+12,j*2-1+6).Value="学号"
Cells(ZuoWei+12,j*2+6).Value="姓名"
Next j
For k=1 To Row1 '第一大排为完整的排
Cells(ZuoWei+12-k,9).Value=Worksheets("高三理科").Cells(Num+k,1).Value
Cells(ZuoWei+12-k,10).Value=Worksheets("高三理科").Cells(Num+k,2).Value
Next k
For k=1 To YuShu-Row1 '第二大排为不完整的排
Cells(ZuoWei+12-k,7).Value=Worksheets("高三理科").Cells(Num+Row1+k,1).Value
Cells(ZuoWei+12-k,8).Value=Worksheets("高三理科").Cells(Num+Row1+k,2).Value
Next k
End If
… … (省略到第三大排止和到第四大排止情况)
… …
If YuShu>Row1+Row2+Row3+Row4 And YuShu<=Row1+Row2+Row3+Row4+Row5 Then'到第五大排止
For j=1 To 5'第一大排到第五大排的表头
Cells(ZuoWei+12,j*2-1).Value="学号"
Cells(ZuoWei+12,j*2).Value="姓名"
Next j
For k=1 To Row1'第一大排为完整的排
Cells(ZuoWei+12-k,9).Value=Worksheets("高三理科").Cells(Num+k,1).Value
Cells(ZuoWei+12-k,10).Value=Worksheets("高三理科").Cells(Num+k,2).Value
Next k
For k=1 To Row2'第二大排为完整的排
Cells(ZuoWei+12-k,7).Value=Worksheets("高三理科").Cells(Num+Row1+k,1).Value
Cells(ZuoWei+12-k,8).Value=Worksheets("高三理科").Cells(Num+Row1+k,2).Value
Next k
For k=1 To Row3'第三大排为完整的排
Cells(ZuoWei+12-k,5).Value=Worksheets("高三理科").Cells(Num+Row1+Row2+k,1).Value
Cells(ZuoWei+12-k,6).Value=Worksheets("高三理科").Cells(Num+Row1+Row2+k,2).Value
Next k
For k=1 To Row4'第四大排为完整的排
Cells(ZuoWei+12-k,3).Value=Worksheets("高三理科").Cells(Num+Row1+Row2+Row3+k,1).Value
Cells(ZuoWei+12-k,4).Value=Worksheets("高三理科").Cells(Num+Row1+Row2+Row3+k,2).Value
Next k
For k=1 To YuShu-Row1-Row2-Row3-Row4'第五大排为不完整的排
Cells(ZuoWei+12-k,1).Value=Worksheets("高三理科").Cells(Num+Row1+Row2+Row3+Row4+k,1).Value
Cells(ZuoWei+12-k,2).Value=Worksheets("高三理科").Cells(Num+Row1+Row2+Row3+Row4+k,2).Value
Next k
End If
Cells(ZuoWei+13,5).Value="讲台"
Cells(ZuoWei+14,5).Value="高三理科第"&ZongShiChang+ShiChangHao&"试场"'试场号
ZuoWei=ZuoWei+15
Cells(ZuoWei,1).Activate
ActiveSheet.HPageBreaks.Add before:=ActiveCell'插入分页符
End If
End Sub
该模块生成各班级学生考试座位表,告知学生考试座位所在试场,在程序代码中,对“高三理科”工作表先进行学号排序,再分别利用循环语句从“试场分布”工作表中拷贝粘贴试场位置和“高三理科”工作表第一行列字段,最后形成如图4所示的“高三理科”工作表,其程序代码如下:
Sub BanJiBiao()'生成班级座位表
Dim k As Integer
Dim BanJi As Integer '指向各班级开头行号
Dim i As Integer
Worksheets("高三理科").Activate
Gao3Row=1
For k=1 To Gao3LiBanShu
Gao3Row=Gao3Row+Gao3Li(k)'高三理科表有效行数
Next k
Cells(Gao3Row,3).Select
Range(Selection,"a2").Select
Selection.Sort key1:=Columns(1),order1:=xlAscending '进行学号排序
Cells(1,4).Value="试场号"
Cells(1,5).Value="试场位置"
BanJi=2 '初始化
For i=1 To Gao3LiBanShu
Worksheets("试场分布").Activate '激活试场分布表
Cells(ShiChangHao+ZongShiChang+1,2).Select
Range(Selection,"a"&1+ShiChangHao+1).Copy '拷贝试场位置分布
Worksheets("高三理科").Activate
Cells(BanJi,4).Select
ActiveSheet.Paste '粘贴高三理科试场位置分布
BanJi=BanJi+Gao3Li(i)
Next i
For i=Gao3LiBanShu To 2 Step-1
Cells(1,1).Select
Selection.EntireRow.Select
Selection.Copy'复制第一行列字段
Gao3Row=Gao3Row-Gao3Li(i)
Cells(Gao3Row+1,1).Select
Selection.EntireRow.Insert'插入一行
ActiveSheet.Paste '粘贴列字段
ActiveSheet.HPageBreaks.Add before:=ActiveCell'插入分页符
Next i
ShiChangHao=ShiChangHao+ZongShiChang '计算试场号,以便排别的试场
End Sub
[1](美)杰克(Jerke,N.).VisualBasic 5开发人员指南[M].北京:机械工业出版社,1997.10.