柳孔明,赵波,张一平
(中国人民解放军95806部队,北京100076)
“全军各级要强化练兵备战鲜明导向,坚定不移把军事训练摆在战略位置、作为中心工作,抓住不放,抓出成效。”新年伊始,中央军委举行2018年开训动员大会,习主席向全军发布了训令,全军各级掀起了体能训练的热潮。由于体能训练考核科目涉及较多,且考核成绩按照人员类别、性别、年龄段有不同的考核科目,且给出了不同的成绩计算标准,这就给工作人员根据成绩计算出各科目的得分,并最终给出综合评价结果带来较大的困难。如果采取人工方式通过Excel表进行汇集统计计算,再依照模板填写到Word文档中去,会花费大量人力物力,并且效率低下,增加了出错的概率,会影响领导对考核成绩的信息的及时把握、分析和判断。
对军人体能训练考核中人工计算成绩中存在的现实问题,通过设计和开发专门的信息系统可以轻松解决。本文基于通过自动匹配成绩区间来计算考核分数的基本思路,采用DevExpress界面开发控件库,利用C#语言开发了军人体能考核成绩计算系统,并进行了大量的测试,在实际应用中极大提高了计算效率和正确率。本文将对系统软件的设计与开发的关键技术进行简要阐述。
军人体能考核成绩计算系统旨在利用计算机技术实现军人体能训练考核成绩计算信息化、标准化,减轻重复繁重的工作负担,同时达到体能标准查询、按照成绩计算得分及评价、按照模板进行结果输出等简单易操作性。进行系统设计时,考虑到成绩数据中有些符号如分钟(′)、秒(″)在录入过程中可能由于中英文字符难以区分等因素造成输入不规范,程序中采取最大兼容方式规避了可能出现的问题。系统主要实现了考核成绩的导入、得分与评价计算、数据按照模板的导出等主要功能。
系统建立了体型标准表(T_TX)、体脂标准表(T_TZ)、引体向上标准表(T_YTXS)、仰卧起坐标准表(T_YWQZ)、曲臂悬垂标准表(T_QBXC)、俯卧撑标准表(T_FWC)、蛇形跑标准表(T_SX2)、3000 米跑标准表(T_3000)、成绩统计表(T_SCORE)等。系统中涉及的数据表较多,由于篇幅限制,这里只给出体型标准表(T_TX)简约数据表结构(主要字段信息),如表1所示。
表1 体型标准表(T_TX)简约数据表结构
军人体能考核成绩计算系统是典型的信息系统,系统采用C/S架构,以C#作为系统的程序设计语言,以Visual Studio 2013为系统集成开发平台,系统数据库采用Microsoft Office Access。Microsoft公司的Access是一个桌面关系型数据库管理系统,能够制作窗体和报表,并且能够与Excel进行数据交换。Access适合开发小型数据库应用系统。该系统采用Access 2000进行开发。
系统的设计采取软件工程中“自下而上”的方法,实现各个业务功能。系统开发主要包括后台数据库的建立和维护以及前端应用程序的开发两个方面,对于前者要求建立起数据一致性和完整性强、数据安全性好的库。而对于后者则要求应用程序功能完备,易使用等特点。
(1)Excel数据的导入
因为使用Excel来操作数据很方便,在数据登记时采用Excel登记数据可以给用户带来很多方便,因此为了便于数据流转需要,我们需要提供一个入口给用户导入所需要的数据。
C#操作Excel的传统方式主要有以下几种方式:①采用OleDB读取Excel文件,把Excel文件当做一个数据源来进行数据的读取操作;②通过引用COM组件Microsoft.Office.Interop.Excel.dll读取;③将Excel文件转化成CSV文件,利用文件流的方式读取。但是上述方法都较为过时,并且或者操作比较繁琐,或者对组件版本依赖性较强,客户机通用性差。这里采用NPOI动态库进行开发,NPOI是开源的POI项目.NET版,可以用来读写Excel等Office文档,在处理Excel文件方面,NPOI可以同时兼容*.xls和*.xlsx格式,具有开源免费、不依赖Office组件、简单方面、性能稳定等优点。程序中的关键代码如下:private void ReadExcelData()
{
FileStream fs=null;
NPOI.SS.UserModel.IWorkbook workbook=null;
ISheet sheet=null;
var filePath=openFileDialog.FileName;
ExcelPath=filePath;
try
{
//读取文件的sheet页
using(fs=File.OpenRead(filePath))
{
if(filePath.IndexOf(".xlsx")>0)//Excel 2007版本
workbook=new XSSFWorkbook(fs);
else if(filePath.IndexOf(".xls")>0)//Excel 2003版本
workbook=new HSSFWorkbook(fs);
((DevExpress.XtraEditors.Repository.RepositoryItemComboBox)
this.barEditItem1.Edit).Items.Clear();
if(workbook!=null)
{
object dafaultSheet="";
for(int i=0;i { sheet=workbook.GetSheetAt(i);//循环读取每个 sheet页面 ((DevExpress.XtraEditors.Repository.RepositoryItemComboBox)this.barEditItem1.Edit).Items.Add(sheet.SheetName);//加载各个sheet表的名称到下拉框中供选择 if(i==0) dafaultSheet=sheet.SheetName; } if(workbook.NumberOfSheets==1)//如果只有一个sheet页,则默认加载数据 this.barEditItem1.EditValue=dafaultSheet; else//如果有多个页面,则提示用户从下拉框中选择需要加载的数据源 MessageBox.Show("请在下拉框中选择需要计算的Sheet表单,并提交计算!"); } } } } (2)LINQ to SQL技术实现根据考核成绩计算分数 使用LINQ to SQL技术,主要由以下几个优点:一是把查询语法直接融入C#语言,关键词高亮显示,支持类型检查,允许使用debugger调试,便于程序开发;二是把之前复杂的查询工作封装起来,语法更加清晰易懂,可读性较高;三是通过LINQ查询内存数据,避免了多次与数据库的连接延迟,极大提升了程序的执行效率。 需要特别指出的是,在计算过程中针对考核成绩大于100分的分数按照各考核项目的给出的处理方法做了处理;针对考核成绩下限,按照不同类别的人员进行了成绩归零处理。以仰卧起坐分数计算为例,程序中的关键代码如下: private void CalculateScore() { ...(省略部分代码) //// 2.2 计算仰卧起坐分数 var result2=from b in dt_YWQZ.AsEnumerable() where b.Field where b.Field //where a.Field select b; double max_YWQZ=0;string score_YWQZ="0"; foreach(var item in result2) { if(p.YWQZ continue; else if (max_YWQZ < Convert.ToDouble(item["V_NUM"])) { max_YWQZ=Convert.ToDouble(item["V_NUM"]); score_YWQZ=item["SCORE"].ToString(); } //MessageBox.Show(item["ID"].ToString()+"******"+item["V_NUM"].ToString());// } this.gridView1.SetRowCellValue(i,"仰卧起坐分数",score_YWQZ); //如果超出100分 if(score_YWQZ=="100") { this.gridView1.SetRowCellValue(i,"仰卧起坐分数",(100+Math.Floor((p.YWQZ-max_YWQZ)/2)).ToString()); } else if(Convert.ToDouble(score_YWQZ)<65)//按照人员类别计算不及格人员分数 { if(p.RYLB=="一类") this.gridView1.SetRowCellValue(i,"仰卧起坐分数","0"); else if(p.RYLB=="二类"&&Convert.ToDouble(score_YWQZ)<60) this.gridView1.SetRowCellValue(i,"仰卧起坐分数","0"); else if(p.RYLB=="三类"&&Convert.ToDouble(score_YWQZ)<55) this.gridView1.SetRowCellValue(i,"仰卧起坐分数","0"); } ...(省略部分代码) } (3)考核分数表的输出 通过Aspose.Words类库,利用Word模板实现静态的创建和填充Word文档(即:通过Bookmark书签填充文档内容),可以不依赖Word组件的安装,方便地实现数据按照既定模板的导出功能。这需要事先制作好成绩输出的Word模板,并在模板中添加相应的书签标记。这里按照模板要求,做了各个表格位置的标签,有xh1-xh10(对应各行的序号),…,zp1-zp10(对应各行的总评)。特别需要指出的是,由于需要计算的人数不同,而在标准输出模板中每页最多可以输出10人成绩,这里采用了按照10人一组(最后不满10人的为一组)输出成为一个单独文档,再将各个文档合并成一个文档的方法实现。同时,为了输出数据的标准化,系统设置了数据的输出标准统一格式,增添了数据可读性。程序中的关键代码如下: private static void CreateDocumentByBookmark(string template⁃Path,string targetPath) { string templatePath=Application.StartupPath+@"模板.docx";//模板文件 string savePath=null;//最终生成的文件(如果是多个文件的话 需要合成) SaveFileDialog saveFileDialog1=new SaveFileDialog(); saveFileDialog1.Filter="Word文档(*.docx)|*.docx"; saveFileDialog1.RestoreDirectory=true; if(saveFileDialog1.ShowDialog()==DialogResult.OK)//选择输出的文件名称和路径 { savePath=saveFileDialog1.FileName;//输出的文件名 //创建word文档 if(File.Exists(templatePath)) { int docCount=(int)Math.Ceiling(this.gridView1.Row⁃Count/10.0);//计算需要拆分的word数量 for(int j=0;j { //加载word模板文件 Aspose.Words.Document doc=new Aspose.Words.Document(templatePath); Aspose.Words.DocumentBuilder builder=new As⁃pose.Words.DocumentBuilder(doc); if(j { for(int i=0;i<10;i++) //按照每行的书签逐个表格添加数据 { //1序号 string bookmarkName="xh"+(i+1).ToString();//计算出需要填写的书签名 builder.MoveToBookmark(bookmarkName);//通过移动光标到指定的书签名,写入内容 builder.Write((j*10+i+1).ToString());//将相应的内容填写到指定的标签位置 //2姓名 …此处省略相似代码 } } else { //将数据逐行加入到文档中 写标签 for(int i=0;i { //按照每行的书签逐个表格添加数据 //1序号 string bookmarkName="xh"+(i+1).ToString(); builder.MoveToBookmark(bookmarkName);builder.Write((j*10+i+1).ToString()); //2姓名 ……此处省略相似代码 } } //添加表头单位信息 string headmarkName="dm"; builder.MoveToBookmark(headmarkName); builder.Write((this.barEditItem2.EditValue.ToString())); doc.Save(Application.StartupPath+"\temp\"+j.ToString()+".docx",Aspose.Words.SaveFormat.Docx);//文档的保存,每10行保存为1个单独word文档 } //进行多个文档的合成最终输出文档 Aspose.Words.Document docx=new Aspose.Words.Document(); docx.RemoveAllChildren(); for(int i=0;i { string fp=Application.StartupPath+"\temp\"+i.ToString()+".docx"; FileStream fs=new FileStream(fp,FileMode.Open); Aspose.Words.Document doc=new Aspose.Words.Document(fs); docx.AppendDocument(doc,Aspose.Words.Import⁃FormatMode.UseDestinationStyles); fs.Dispose();fs.Close(); } docx.Save(savePath, Aspose.Words.SaveFormat.Docx);//保存合成结果 } } } 系统运行的界面效果如图1所示,其中黄色背景的列为要导入(或输入)的数据列,属公共考核科目或个人信息内容;红色背景列为男军人专有考核项目;绿色背景列为女军人专有考核项目;无背景列为系统计算并自动填充的考核分数列;蓝色背景列为最终得分统计及总评结果列。结果显示非常直观。 图1 成绩计算功能主界面 图2为系统计算结果按照预定模板输出的登记表。 图3为体型标准数据查看界面,界面采用了Dev⁃Express控件,可以方便的实现数据的按列分组,按关键字进行查询筛选等功能。 本文针对军人体能考核成绩计算过程中存在的实际困难,详细分析系统所需关键技术,利用计算机技术和数据库技术,设计并实现了军人体能考核成绩计算系统,并对系统进行了详细测试。系统目前已经顺利运行,切实满足了单位的实际需要,提高了考核成绩的及计算输出效率和正确率,极大降低了人工作业难度,可以在广大军警院校及部队推广使用。 图2 计算结果输出表3 系统运行效果
4 结语