在各高等、中等院校的计算机类课程中,计算机基本应用技能的上机操作考试,广受重视,大为盛行。其中,office(word、excel、ppt)上机考试最为普遍。于是,实现这类Office文档操作的自动阅卷评分,很有必要。本人最近项目上刚好遇到需要解决这种自动评分的问题,所以再次记录下解决的方法思路。
一、预备知识不管是Office还是WPS,都提供了加载项技术的开发,加载项开发是一套基于 Web 技术用来扩展 Office / WPS 应用程序的解决方案, 都可以能够对现有功能的扩展开发,
WPS加载项文档:https://open.wps.cn/previous/docs/client/wpsLoad
Office加载项文档:https://learn.microsoft.com/zh-cn/office/dev/add-ins/
具体环境的搭建以及使用方法请看各自的文档。
下面代码基本都是伪代码方式,不可直接运行,只是表达其逻辑,具体情况以实际情况为主,这里已WPS加载项为例, 比如如下文档示例。
# 获取文档第一段的对齐方式
Application.ActiveDocument.Paragraphs.Item(1).Alignment;
# 获取文档第一段的文本呢日哦那个
Application.ActiveDocument.Paragraphs.Item(1).Range.Text
其可以使用javascript来对文档进行读取、操作。
二、测评方法先看一个WPS操作题目的样子。
将页面纸张类型设置为自定义大小,宽度540磅,高度810磅;
给文章加标题“越剧服饰简介”,设置标题字体为黑体、二号字、加粗倾斜、橙色,段前间距0.5行段后间距为1行,水平居中显示,并设置为1级标题。
将正文所有段落设置为首行缩进2字符;设置正文所有中文字体为仿宋5号,行间距设置固定值20;给正文小标题“古装衣”、“越剧蟒”、“越剧裙”、“褶子与帔”、“越剧盔帽”、“越剧靴鞋”设置为黑体小四号、首行缩进0字符,加1.5磅的黑色边框,填充橙色底纹(边框、填充色应用于段落)。
在正文第3段(“4个小鬼的服装作了设计;……”)插入图片xf.jpg(图片在当前试题文件夹下),设置图片的高度、宽度分别为8.4cm和6.15cm,环绕方式为四周型、水平对齐方式为居中,并加蓝色、1.5磅单实线边框。
在第2页右上角插入自选图形“思想气泡:云”,并添加文字“越剧服饰”,设置图形填充色为橙色,线条为蓝色,环绕方式为紧密型;
设置奇数页页眉为“越剧服饰”,偶数页页眉为“中国越剧”,均居中显示,显示奇偶页眉线;所有页页脚均为“第1页”样式,起始页码为第2页。
将t1.txt(在当前试题文件夹下)文件中的内容添加到文档的最后位置;将其文档内容转换成6行3列表格(转换不包括“附表:”行),设置表格对齐方式为居中,设置“附表:我国越剧代表作”居中,设置表格列宽为110磅;设置表格外边框为2.25磅红色单实线、内边框为0.5磅蓝色单实线;表格第一行填充橙色底纹;表格对齐方式为居中对齐,单元格对齐方式为水平居中、垂直居中。
使用邮件合并功能:将当前试题文件夹下的电子表格“考生信息.xlsx”中的信息插入到文档最后一段表格的后面,匹配域设置唯一标识符匹配准考证号,尊称匹配姓名。在插入合并域中选择地址域,插入唯一标识符和尊称显示准考证号和姓名。生成的新文档以文件名“考生信息.docx”保存到当前试题文件夹中。
对于上面的题目,可以将测评分为多个指标点来进行评测,每个指标点一个分数。考虑到测评包括教师出题界面、学生作答评分,则其指标点结构可以如下设计:
- 指标点名:该测评点的名称,用作显示或成绩报告中显示用。
- 出题参数:指定配置在出题界面评测该点需要的参数,该部分可以按照动态表单 组件化的思想来设计,并且尽量和WPS/Office中的操作保持一致,
- 测评代码:评测该点是否正确与否的代码,该代码返回true或者false,也就是代表是否得分。该代码在开发时预设好,后续也可以动态增加调整,该代码的编写质量能直接影响到该测评点的正确性,因此很关键。
- 得分:该测评点的分数
该测评方法的重点在出题参数、测评代码这里,在开发的时候,开发者开发设计好出题参数、测评代码将其入库,教师在出题的时候其出题界面根据出题参数进行渲染出界面进行设置,学生作答后在其相应的软件上运行测评代码,根据其返回的结果(true/false)来进行判断是否得分。因为测评点信息保存在库中,这样后面在使用过程中也可以动态更新调整测评点。
三、出题参数的设计那具体怎样设计出题参数以及测评代码呢、这个得根据经验、考纲要求、对WPS/Office的掌握程度等,需要知道哪些点需要测评,比如文档标题,页面设置等,最简单的是根据客户提供的题目信息,然后从中抽取分析出指标点, 先以满足用户需要的点,后续在动态增加。比如如上的题目信息中的第一小问:
将页面纸张类型设置为自定义大小,宽度540磅,高度810磅;
对于这个描述,可以知道页面的纸张大小是一个测评点,那可以如下设计。
- 先参考文档中页面是怎样设置的。
如下是在WPS文档中纸张大小的设置。
可以看到,纸张大小在设置的时候是一个下拉框, 里面有可以设置A4、6号信封、7号信封等等。
但是得注意,还有一个自定义大小,当选择了自定义大小,或者手动调整宽高后其下拉框自动变成了自定义大小,这个时候就可以手动输入一个自己想要的宽高。
因此在设计出题参数的时候肯定有一个纸张纸张大小的下拉框、一个宽度的输入框、宽度单位的下拉框,一个高度的输入框、高度单位的下拉框,然后当纸张大小的下拉框的值是自定义大小的时候其他的输入框显示。输入框是最简单的,直接放上输入框input就可以了,教师端直接输入,但是下拉框选择的value值得注意,不一定是在界面上展示的那个样子,比如当选择A4的时候,其获取下来的值为7, 6号信封为41。
# 当设置为A4
Application.ActiveDocument.PageSetup.PaperSize # 结果为7
# 当设置为6号信封
Application.ActiveDocument.PageSetup.PaperSize # 结果为41
# 当设置为7号信封
Application.ActiveDocument.PageSetup.PaperSize # 结果为31
因此每个值都需要用代码获取到。值拿到了,按照动态表单的设计,其出题参数的结构也就有出来了,如下示例:
[
{
"name": "paperSize",
"label": "纸张大小",
"type": "select",
"defaultValue": 7,
"options": [
{
"label": "A4大小",
"value": 0
},
{
"label": "11x17英寸",
"value": 1
},
{
"label": "A3",
"value": 6
},
{
"label": "A4",
"value": 7
},
{
"label": "小A4",
"value": 8
},
{
"label": "A5",
"value": 9
},
{
"label": "B4",
"value": 10
},
{
"label": "B5",
"value": 11
},
{
"label": "C Sheet",
"value": 12
},
{
"label": "自定义纸张大小",
"value": 41
},
{
"label": "D Sheet",
"value": 13
},
{
"label": "正规信封10尺寸",
"value": 25
},
{
"label": "11寸信封",
"value": 26
},
{
"label": "12寸信封",
"value": 27
},
{
"label": "14寸信封",
"value": 28
},
{
"label": "9寸信封",
"value": 24
},
{
"label": "B4信封",
"value": 29
},
{
"label": "B5信封",
"value": 30
},
{
"label": "B6信封",
"value": 31
},
{
"label": "C3信封",
"value": 32
},
{
"label": "C4信封",
"value": 33
},
{
"label": "C5信封",
"value": 34
},
{
"label": "C6信封",
"value": 35
},
{
"label": "C65信封",
"value": 36
},
{
"label": "DL信封",
"value": 37
},
{
"label": "意大利式信封",
"value": 38
},
{
"label": "君主式信封",
"value": 39
},
{
"label": "私人信封",
"value": 40
},
{
"label": "E Sheet",
"value": 14
},
{
"label": "行政型尺寸",
"value": 5
},
{
"label": "德国正规复写簿尺寸",
"value": 15
},
{
"label": "德国标准复写簿尺寸",
"value": 16
},
{
"label": "美国复写簿尺寸",
"value": 17
},
{
"label": "对开尺寸",
"value": 18
},
{
"label": "分类帐尺寸",
"value": 19
},
{
"label": "正规尺寸",
"value": 4
},
{
"label": "信函尺寸",
"value": 2
},
{
"label": "小型信函尺寸",
"value": 3
},
{
"label": "便笺尺寸",
"value": 20
},
{
"label": "四开尺寸",
"value": 21
},
{
"label": "报表尺寸",
"value": 22
},
{
"label": "文摘尺寸",
"value": 23
}
]
},
{
"name": "pageWidth",
"label": "宽度",
"type": "input",
"showRule": "${paperSize} == 41", //因为41为自定义纸张大小
},
{
"name": "pageWidthUnit",
"label": "宽度单位",
"type": "select",
"defaultValue": 2,
"showRule": "${paperSize} == 41", //因为41为自定义纸张大小
"options": [
{
"label": "榜",
"value": 0 //自定义的可以根据情况来
},
{
"label": "英寸",
"value": 1
},
{
"label": "厘米",
"value": 2
},
{
"label": "毫米",
"value": 3
}
]
},
{
"name": "pageHeight",
"label": "高度",
"type": "input",
"showRule": "${paperSize} == 41", //因为41为自定义纸张大小
},
{
"name": "pageHeightUnit",
"label": "高度单位",
"type": "select",
"defaultValue": 2,
"showRule": "${paperSize} == 41", //因为41为自定义纸张大小
"options": [
{
"label": "榜",
"value": 0 //自定义的可以根据情况来
},
{
"label": "英寸",
"value": 1
},
{
"label": "厘米",
"value": 2
},
{
"label": "毫米",
"value": 3
}
]
},
]
则在出题界面端,根据如上的参数渲染出界面,其type类型控制表单的类型,可以有常见的输入框,下拉框,单选框,多选框类型等等,复杂的也可以自定义组件来实现。
其他的指标点也是按照这个流程来设计,一条一条往数据库中加,这样测评点覆盖范围就越来越多了
四、测评代码的设计测评代码是根据指标点的功能来编写一段代码来进行测评学生是否作答正确与否的一个操作,比如还是纸张大小,其测评代码如下:
function __eval_MODEL__(paperSize, pageWidth, pageWidthUnit, pageHeight, pageHeightUnit){
if(paperSize != 41) {
// 若不是自定义大小,则比较 PaperSize
return Application.ActiveDocument.PageSetup.PaperSize == paperSize;
}else {
//若是自定义大小,则比较宽高
let pageWidthBang = toSizeBang(pageWidth, pageWidthUnit); //根据设置统一转化为单位榜
let pageHeightBang = toSizeBang(pageHeight, pageHeightUnit); //根据设置统一转化为单位榜
return Application.ActiveDocument.PageSetup.PageWidth == pageWidthBang && Application.ActiveDocument.PageSetup.PageHeight == pageHeightBang
}
}
如上则为一个测评纸张大小的测评代码示例。最后在设置一个分数,则该指标点就差不多设计完成了
五、测评方法当指标点设置完成后,其在学生端这个指标点的测评流程为根据其其出题参数、测评代码去生成一段能运行的代码。
function evalPoint1(point) {
//这里为编写的测评代码,直接从point中读取过来
function __EVAL_MODEL__(paperSize, pageWidth, pageWidthUnit, pageHeight, pageHeightUnit){
//....
}
//这几个参数为根据出题界面教师设置的内容进行生成,一般为保存在point中
var _paperSize=41;
var _pageWidth=undefined;
var _pageWidthUnit=undefined;
var _pageHeight=8;
var _pageHeightUnit=1;
//调用
return __EVAL_MODEL__(_paperSize, _pageWidth, _pageWidthUnit, _pageHeight, _pageHeightUnit)
}
则测评流程为:
let score = 0;
for(let i = 0; i < points.length; i ) {
if(evalPoint(points[i])) {
score = points[i].score;
}
}
//score为总分了
,