zoukankan      html  css  js  c++  java
  • 看数学老师是如何一键搞定报告和试卷的

    本文将介绍Matlab的两个实用技巧。一键生成Word版本的报告和PDF版本的数学试卷。其中第一个技巧Matlab之前都是通过调用COM接口来实现的,类似于VBA,虽然可做的事情很多,但并不适合一般的童鞋。第二个技巧,灵感来源于一位研究僧同学。大致意思是根据现有的数学题库来科学快捷的生成一份试卷。本文提供的只是初稿,如果需求大的话,作者会在Github上保持更新。

    文/JSong 转载请注明出处! 原文地址

    1. 自动化报告

    测试平台: MATLAB 2015b

    先来看一个最简单的例子(demo1.m)

    % demo1.m
    import mlreportgen.dom.*;
    d = Document('demo1','docx');
    open(d);
    append(d,'hello world!');
    close(d);
    rptview(d.OutputPath);
    
    import mlreportgen.dom.*;
    

    第一行是将所需要的类和函数导入工作空间。这里我们最常用的类就是Document.

    d = Document('test','docx');
    open(d);
    

    在第二、三行中我们新建一个文档,其中文件类型docx可以替换成html或者pdf. Document类的相关属性可以通过命令查看 (doc mlreportgen.dom.Document)

    append(d,'hello world!');
    

    在第四行我们给文档添加了一句经典的话,我们还可以自定义它们的样式。比如加粗、斜体、改成蓝色、字体大小等等。

    % 替换上面的一行代码
    p=Text('hello world');
    p.Style={Bold(true),FontSize('16pt'),Color('blue')};
    p.Strike='double';
    append(d,p)
    

    这里出现了第一个文档类:Text,即文本。Matlab提供了很多可调节的属性,如下表。修改起来也很方便,如要把文本改为斜体,则添加:p.Italic=1;即可。

    Text的属性 取值 备注
    Bold true/false 加粗
    Color str('red'、'blue'等) 颜色
    Italic true/false 斜体
    BackgroundColor str 背景色
    Underline str('single'、'dotdash'等) 下划线
    FontFamilyName str 字体
    FontSize str('12pt') 字体大小
    Strike str 删除线
    StyleName str 模板中的样式名

    接下来我们将生成一个更复杂的文档。首先想想一个word文档一班都有哪些元素。MATLAB提供了很多(下面的表格仅列出了部分)。本文主要介绍其中的五个:页面设置、标题、段落、表格、图片。

    属性 含义
    CustomAttribute Custom element attribute
    CustomElement Custom element of a document
    CustomText Plain text to be appended to a custom element
    DOCXPageFooter Page footer for a Word document.
    DOCXPageHdrFtr Page Base class for page header and footer
    DOCXPageHeader Page header for a Word document.
    DOCXPageMargins Margins of pages in a Word page layout
    DOCXPageSize Size, orientation of pages in a Word layout
    DOCXSection Page layout section of a Word document
    Document Create a dom document
    ExternalLink Create a hyperlink to an external target
    Form Defines a form
    FormalTable Create a formal table
    Group Group of document objects
    Heading Create a heading paragraph.
    HorizontalRule Create a horizontal rule.
    Image Create an image to be included in a report.
    ImageArea Defines an image area as a hyperlink
    InternalLink Create a hyperlink to a target in this
    LinkTarget Create a target for a hyperlink.
    ListItem Item in a list
    Node Defines a document node
    Object Defines a document object
    OrderedList Ordered (numbered) list
    Paragraph Create a formatted block of text, i.e., a paragraph.
    Table Create a table.
    TableColSpecGroup Defines style of a group of table columns
    TableEntry Create a table Entry
    TableRow Creates a table row
    Template Create a template for a document
    Text Create a text object

    接下来我们做一个完整的模板。首先新建空白文档。

    % demo2.m
    import mlreportgen.dom.*;
    d=Document('demo2','docx');
    open(d);
    

    1.1 页面

    页面设置包括页面大小('A4'等)、页面方向、页边距.

    % 页面设置
    s = d.CurrentDOCXSection;
    s.PageSize.Orientation  ='landscape'; % portrait(default)
    s.PageSize.Height = '8.5in';
    s.PageSize.Width = '11in';
    s.PageMargins.Left = '3.0cm';
    s.PageMargins.Right = '3.0cm';
    s.PageMargins.Top = '2.5cm';
    s.PageMargins.Bottom = '2.5cm';
    % 中文字体样式设置
    heiti=FontFamily;
    heiti.FamilyName='Arial';
    heiti.EastAsiaFamilyName='黑体';
    songti=FontFamily;
    songti.FamilyName='Arial';
    songti.EastAsiaFamilyName='宋体';
    

    1.2 标题

    标题的初始格式由模板中自带的标题样式决定,当然也可以自己修改。

    %% 标题
    p=Heading(1,'Matlab 自动化报告模板');% 一级标题
    %p.Color='red';
    %p.HAlign='center';
    p.Style={heiti,Color('red'),HAlign('center')};
    append(d,p);
    

    1.3 段落

    与文本不同,段落除下文本的属性外,还有边距、对齐、首行缩进、行间距、段前、段后等属性需要调节。在下面的代码框中,FirstLineIndent代表首行缩进的宽度,LineSpacing代表行间距,OuterMargin代表边距。在这里我们还引入了一个新的类:ExternalLink(外部链接),当然Matlab也提供文档内部链接:InternalLink.

    %% 段落
    append(d,Heading(2,'一、段落模板'));
    s='这里是段落。';
    s=repmat(s,[1,12]);
    p = Paragraph(s);
    % 中文字体样式自定义
    p.Style={songti,Color('blue'),...
        LineSpacing(1.5),...
        OuterMargin('10pt','0pt','0pt','10pt')};
    p1=Text('下划线。');%同段落差不多.
    p1.Underline='single';
    p1.Color='red';
    append(p,p1);
    append(p,s);
    p2=ExternalLink('http://github.com/gasongjian/', '超链接');
    append(p,p2);
    p.FontSize='14pt';
    p.FirstLineIndent='28pt';%这里差不多就是2个字符大小
    append(d,p);
    

    1.4 简易表格

    Matlab 支持直接从数组矩阵和元胞矩阵建立表格。如t=Table(magic(5))或者
    t=Table(cell(5)). 也可以利用TableRow一行一行添加。一个单元格可以填充的元素很多(文本、图像等),所以可调节的就是表格的边框、单元格的大小、对齐等。本文给出一个简易的例子和一个复杂的例子。一件很遗憾的事就是不能合并单元格。当写完demo2后,本文还将提供一种更为简便的方式。

    %% 简易表格
    append(d,Heading(2,'二、简单表格'));
    t={'志明','语文','数学','英语'; ...
        '成绩','70','98','89'; ...
        '等级','B','A','A'};
    p=Table(t);
    
    % 格式化单元格中的段落
    for ii=1:p.NRows
        for jj=1:p.NCols
            t=entry(p,ii,jj);
             t.Children(1).Style={songti,...
                Color('green'),...
                FontSize('12pt'),...
                LineSpacing(1.0),...
                OuterMargin('0pt','0pt','0pt','0pt')};
        end
    end
    
    p.Style = {Border('single','blue','3px'), ...
                   ColSep('single','blue','1px'), ...
                   RowSep('single','blue','1px')};
    
    p.Width = '50%';
    p.HAlign='center';% 居中对齐
    p.TableEntriesHAlign='center';
    p.TableEntriesVAlign='middle';
    append(d,p);
    

    1.5 复杂表格

    %% 复杂表格
    append(d,Heading(2,'三、复杂表格'));
    q = Table(5);
    q.Border = 'single';
    q.ColSep = 'single';
    q.RowSep = 'single';
    
    row = TableRow;
    te = TableEntry('算法名称');
    te.RowSpan = 2;
    append(row, te);
    
    te = TableEntry('第一类');
    te.ColSpan = 2;
    %te.Border = 'single';
    append(row, te);
    te = TableEntry('第二类');
    te.ColSpan = 2;
    %te.Border = 'single';
    append(row, te);
    append(q,row);
    
    % 第二行
    row=TableRow;
    append(row,TableEntry('T1'));
    append(row,TableEntry('T2'));
    append(row,TableEntry('T3'));
    append(row,TableEntry('T4'));
    append(q,row);
    
    % 其他行
    t=TableRow;
    append(t,TableEntry('条目'));
    for i=1:4
        append(t,TableEntry(' '));
    end
    append(q,t);
    append(q,clone(t));
    append(q,clone(t));
    append(q,clone(t));
    q.TableEntriesStyle={Width('80'),Height('40')};
    q.Style = {Border('single','green','3px'), ...
                   ColSep('single','green','1px'), ...
                   RowSep('single','green','1px')};
    
    q.HAlign='center';% 居中对齐 
    q.TableEntriesHAlign='center';
    q.TableEntriesVAlign='middle';
    append(d,q);
    

    1.6 图片

    %% 插入图片
    append(d,Heading(2,'四、图片模板'));
    p1 = Image('myPlot_img.png');
    % ScaleToFit是为了使图片大小适应页面,也可以换成下方的自定义大小设置
    %p1.Style={HAlign('center'),ScaleToFit(1)};
    p1.Style={HAlign('center'),Width('600px'),Height('400px')};
    append(d,p1);
    
    close(d);
    rptview(d.OutputPath);
    

    作为一个懒人,我希望写得更极致一点, 即我只想关注内容而忽略这些格式。这时候我们可以利用模板来实现这一切,把所需要的样式都存在模板里。事实上新建Word文档都是基于模板建立的,Matlab也是。通过在模板里修改默认样式或者新建样式,我们可以极大简化上述代码,从而使得上述工作不那么像编程。

    1.7 巧用模板来简化代码

    % demo3.m
    % 利用模板中的样式来生成报告
    % 如果是中文版Word,自带样式名称请参见目录下的pdf文档
    
    import mlreportgen.dom.*
    % 模板文件 mytemplate.dotx 在文末会附下载链接
    d=Document('demo3','docx',fullfile(pwd,'mytemplate'));
    open(d);
    %% 标题
    p=Paragraph('成绩报告单','Heading 1');
    append(d,p);
    %% 文字段落(doc mlreportgen.dom.Paragraph)
    append(d,Heading(2,'一、段落模板'));
    s='这里是段落';
    s=repmat(s,[1,30]);
    p = Paragraph(s,'mypara1');%自定义段落样式
    append(d,p);
    %% 添加空的段落行
    for i=1:8
        append(d,' ');
    end
    %% 插入表格
    append(d,Heading(2,'二、表格模板'));
    t={'姓名','语文','数学','英语'; ...
        '成绩','70','94','82'; ...
        '等级','C','A','B'}; 
    p=Table(t,'mytable1');% 自定义表格样式
    append(d,p);
    close(d);
    rptview(d.OutputPath);
    
    

    到这一个完整的模板就差不多了,还有一些新的类需要读者自己去探索。 接下来才是本文的正题,我们来玩一点好玩的事情。

    2. 批量生成成绩单

    数据集和目标:

    1. 班级所有人的成绩表(成绩.xlsx):姓名、语文、数学、总分;
    2. 给每个同学生一张成绩单,其中只有自己一个人的分数和相对应的等级。
    % SchoolReport.m
    % n=学生人数
    % 为使得程序可读性加强,我们需要格式化成绩单
    % 1. 第一行格式:姓名,各个学科,总分
    % 2. 只有学生成绩,没有其他很杂的信息。
    % 3. 部分成绩若空缺,请不要用数字填充,可以空着或者文字(缺考)填充。
    
    %% 数据导入
    filename='成绩.xlsx';
    savename='成绩单';
    [score,textdata]=xlsread(filename);
    m=3; %学科数
    n=size(score,1);% 学生人数
    name=textdata(2:n+1,1);
    mean_score=mean(score,'omitnan');
    max_score=max(score,[],'omitnan');
    grade=Gradegen(score); %Gradegen是自定义函数,生成各个同学的等级
    
    %模板,实考对应变量score,等级对应变量grade
    template=cell(5,m+1);
    template(1,1:m+1)={'姓名','语文','数学','总分'};
    template(2:5,1)={'实考成绩';'平均成绩';'最高成绩';'等级'};
    
    %% 相关接口
    import mlreportgen.dom.*;
    d = Document(savename,'docx',fullfile(pwd,'mytemplate'));
    open(d);
    
    %% 开始生成word成绩单列表
    
    % 添加分割线
    hr = HorizontalRule();
    hr.Style={Border('dotdash','blue','2px')};
    append(d,hr);
    % n是学生人数,m是学科数
    for i=1:n
        % 填充表格
        template{1,1}=name{i};
        for jj=2:m+1
            s=score(i,jj-1);
            if isnan(s)
                s='缺考';
            else
                s=num2str(s);
            end
            template{2,jj}=s;% 具体分数
            template{3,jj}=sprintf('%4.2f',mean_score(jj-1));%学科平均分数
            template{4,jj}=num2str(max_score(jj-1));%学科最高分数
            template{5,jj}=grade{i,jj-1};% 等级
        end
    
        q=Table(template,'mytable2'); 
        q.TableEntriesStyle={Width('100'),Height('50')};
        append(d,q);
        append(d,clone(hr));
    end
    close(d);
    rptview(d.OutputPath);
    

    成果预览:

    schoolreport.png

    除此之外,本文还提供了一个批量生成奖状的模板(在Word里也可以通过邮件合并功能实现)供参考。

    奖状.png

    相关文件下载链接: 自动化报告 github 项目地址

    3. 中学数学试卷生成

    在写这个之前,首先要感谢一位数学系学长鲍宏昌。接下来要介绍的项目就是基于学长开发的中学试卷包:bhcexam

    项目名称: MathExamGen
    项目平台: Windows+Matlab+Texlive(含bhcexam包)
    项目地址: http://github.com/gasongjian/mathexamgen/
    项目介绍:大体思路就是利用Matlab科学的整合数学题库中的题目,然后生成相应的tex文件,最后借助自带的xelatex编译器编译成pdf文件。

    3.1 数学题库

    存储类型:csv或者数据库
    变量列表:

    变量 变量名 描述 取值
    1 ID 题目编号 6位数字
    2 qtype 题目类型 1代表填空题,2代表选择题等
    3 question 题目内容 题目的latex代码
    4 options 题目相关信息 选择题的四个选项等信息
    5 answer 题目答案
    6 topic 题目的考点 分级考点,如:高二-数列-递推

    3.2 主要思路

    结合Matlab的数据处理与分析功能,我们可以做很多事,例如

    1. 根据给定的类型要求和考点要求,随机生成一张试卷;
    2. 结合单个同学的历史数据,生成适合他/她的试卷,在这份试卷中易错点出现的频次更高一些;
    3. 由于所有试卷都是生成的,我们可以更科学快捷的评估单次考试。

    exam.png

    再次附上项目链接: 自动化报告 github 项目地址数学试卷生成 github 项目地址


    本人公众号,文章首发于此,欢迎关注

  • 相关阅读:
    曾国藩家书人但有恒、事无不成
    pythonredis
    tableSorter使用介绍
    Python模块学习 subprocess 创建子进程
    曾国藩家书用人必先知人
    身份证号码的规则及验证原理
    KeyDown,KeyPress 和KeyUp 之我谈(更新版本)
    Python基础综合练习
    熟悉常用的Linux操作
    大数据概述
  • 原文地址:https://www.cnblogs.com/gasongjian/p/5666993.html
Copyright © 2011-2022 走看看