java POI + freemarker 模板实现word导出

公司最近需要实现word导出功能,并且要去需要用到freemarker模板形式。由于之前只做过poi的Excel导出,对word导出陌生的很。这次算是有机会接触,赶紧记下来。

要求模板:
红色框部分单选多选要求均为变量

20181022141639.png


接下来就是代码的实现部分

1. 替换模板变量

先把文字部分变量替换成所需值


QQ.png

2. 创建实体对象

@Data
public class NursingRecordWordEntity implements Serializable {
    private static final long serialVersionUID = 6435335655833720074L;

    /**
     * 患者姓名
     */
    private String patName;

    /**
     * 记录时间
     */
    private String dateTime;

    /**
     * 记录人
     */
    private String recorder;

    /**
     * 住院号
     */
    private String admissionNumber;

    /**
     * 床号
     */
    private String bedNo;

    /**
     * 入院日期
     */
    private String date;

    /**
     * 诊断
     */
    private String diagnose;

    /**
     * 左瞳孔
     */
    private String leftPupil;

    /**
     * 右瞳孔
     */
    private String rightPupil;

    /**
     * 体温
     */
    private String temp;

    /**
     * 脉搏
     */
    private String pulse;

    /**
     * 呼吸
     */
    private String breathe;

    /**
     * 心率
     */
    private String heartRate;

    /**
     * 血压
     */
    private String bloodPressure;

    /**
     * 氧饱和度
     */
    private String spo;

    /**
     * 氧流量
     */
    private String oxygenflow;

    /**
     * 血糖
     */
    private String glu;

    /**
     * cvp
     */
    private String cvp;

    /**
     * 意识: 清醒       模糊       嗜睡        昏睡        浅昏睡        深昏睡       谵妄状态
     */
    private String consciousness;

    /**
     * 病情: 重         危         管通
     */
    private String condition;

    /**
     * 卧位:  左         右         平卧        端坐        俯            仰           半坐        半卧
     */
    private String clinostatism;

    /**
     * 左眼球摘除
     */
    private String leftPupilRemove;

    /**
     * 右眼球摘除
     */
    private String reghtPupilRemove;

    /**
     * 左眼球瞳孔消失mm
     */
    private String leftPupilDieMM;

    /**
     * 右眼球瞳孔消失mm
     */
    private String reghtPupilDieMM;

    /**
     * 皮肤:  压疮     出血点     颇损     水肿     浸渍     红疹     青紫      肿胀     完整
     */
    private String skin;

    /**
     * 体温类型 :腋度       肛度     耳度     口温     膀胱温度
     */
    private String tempType;

    /**
     * 心电监护
     */
    private String ecg;

    /**
     * 吸痰
     */
    private String sputum;

    /**
     * 皮肤状态(多选)
     */
    /**
     *压疮
     */
    private Boolean pressureSore = false;

    /**
     *出血点
     */
    private Boolean bloodPoint = false;

    /**
     *颇损
     */
    private Boolean damaged = false;

    /**
     *水肿
     */
    private Boolean edema = false;

    /**
     *浸渍
     */
    private Boolean dipping = false;

    /**
     *红疹
     */
    private Boolean erythema = false;

    /**
     *青紫
     */
    private Boolean cyanoze = false;

    /**
     *肿胀
     */
    private Boolean swell = false;

    /**
     *完整
     */
    private Boolean full = false;

}

3. 引入freemarker依赖包

11.png

4. 把替换好变量的word文档另存为.xml

13.png

5. 使用Notepad++等编辑软件打开,对单选、多选进行操作

切记!单选符号、多选符号并不是搜狗输入法里面查询特殊。而是在word的特殊字符中找到想要的效果( Word > 插入 > 符号 > 其他符号(M)..), 也就是字体 Wingdings有我们需要的特殊字符

20180905143747198.png

单选:
<w:sym w:font="Wingdings" w:char="00A4"/>
<w:sym w:font="Wingdings" w:char="00A1"/>
多选:
<w:sym w:font="Wingdings" w:char="00FE"/>
<w:sym w:font="Wingdings" w:char="00A8"/>

然后使用freemarker语法修改.xml内容(例)

<w:r>
  <w:rPr>
        <w:rFonts w:hint="eastAsia"/>
        <w:b w:val="0"/>
        <w:bCs w:val="0"/>
        <w:sz w:val="16"/>
        <w:szCs w:val="20"/>
        <w:vertAlign w:val="baseline"/>
        <w:lang w:val="en-US" w:eastAsia="zh-CN"/>
    </w:rPr>
  <#if reghtPupilRemove == "眼球摘除">
       <w:sym w:font="Wingdings" w:char="00A4"/>
  <#else>
        <w:sym w:font="Wingdings" w:char="00A1"/>
  </#if>
</w:r>
<w:r>

修改完毕另存为后缀 .ftl 文件

6. 修改完毕放入项目目录

12.png

7. 代码实现

public class DocumentHandler {

    private Configuration configuration = null;
    public DocumentHandler() {
        configuration = new Configuration(Configuration.VERSION_2_3_28);
        configuration.setDefaultEncoding("utf-8");
    }
    public void createDoc() {
        //要填入模本的数据文件
        NursingRecordWordEntity data=new NursingRecordWordEntity();
        getData(data);

        //设置模本装置方法和路径,FreeMarker支持多种模板装载方法。可以重servlet,classpath,数据库教程装载,
        configuration.setClassForTemplateLoading(this.getClass(),"/template");
        Template t=null;
        try {
            //test.ftl为要装载的模板
            t = configuration.getTemplate("nursingRecord.ftl");
        } catch (IOException e) {
            e.printStackTrace();
        }
        //输出文档路径及名称
        File outFile = new File("H:\\home\\new_记录单导出模板.docx");
        Writer out = null;
        try {
            out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile), "utf-8"));
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        try {
            t.process(data, out);
        } catch (TemplateException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    /**
     * 注意:
     * 如果是Map那么存放的数据Key值要与模板中的参数相对应
     * 如果是java Bean那么属性名要和模板中的参数相对应
     */
    private void getData(NursingRecordWordEntity data){
        data.setPatName("王二");
        data.setRecorder("老教师");
        data.setAdmissionNumber("123123");
        data.setBedNo("123");
        data.setDate("2019-10-12");
        data.setDateTime("2019-10-12 10:12:33");
        data.setLeftPupil("15");
        data.setLeftPupilRemove(false);
        data.setRightPupil("12");
        data.setReghtPupilRemove(true);
        data.setTemp("60");
        data.setPulse("12");
        data.setBreathe("120");
        data.setHeartRate("120");
        data.setBloodPressure("740/1000");
        data.setSpo("60");
        data.setOxygenflow("99");
        data.setGlu("xx");
        data.setCvp("61");
        data.setClinostatism("左");
        data.setCondition("重");
        data.setConsciousness("昏睡");
        data.setSkin("出血点");
        data.setTempType("肛度");
        data.setEcg("室早");
        data.setSputum("吸痰");
    }
    public static void main(String[] args){
        DocumentHandler dh=new DocumentHandler();
        dh.createDoc();
    }
}

后续

如果想使用流导出只需要如下实现

@RequestMapping(value = "/exportWord")
    public void exportTemplate(NursingRecordWordEntity entity, HttpServletResponse response) {
        log.info("start exportTemplate request is {}", JSON.toJSON(entity));
        ExportWordUtils.createDoc(response, nursingRecordControllerFacade.buildData(entity), EXPORT_WORD_TEMPLATE_NAME, "护理明细doc_" + +System.currentTimeMillis() + ".doc");
        log.info("end exportTemplate..");
    }
public static void createDoc(HttpServletResponse response , Object obj , String templateName , String name) {
        initTemplate();
        Template t = null;
        try {
            t = FTL_CFG.getTemplate(templateName, DEFAULT_CHARSET);
        } catch (IOException e) {
            throw new GWIException("匹配模板获取失败..");
        }

        Writer w = null;
        try {
            // 告诉浏览器用什么软件可以打开此文件
            response.setContentType("application/vnd.ms-excel;charset=utf-8");
            // 下载文件的默认名称
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(name, "utf-8"));
            w = response.getWriter();
            t.process(obj, w);
            w.close();
        } catch (UnsupportedEncodingException e) {
            throw new GWIException(e.toString());
        } catch (IOException e) {
            throw new GWIException(e.toString());
        } catch (TemplateException e) {
            throw new GWIException(e.toString());
        }
    }

至此...word导出功能实现完毕。欢迎大家留言

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,340评论 5 467
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,762评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,329评论 0 329
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,678评论 1 270
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,583评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 47,995评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,493评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,145评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,293评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,250评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,267评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,973评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,556评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,648评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,873评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,257评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,809评论 2 339

推荐阅读更多精彩内容