java使用POI操作XWPFDocument 生成Word实战(一)

注:我使用的word 2016
功能简介:
(1)使用jsoup解析html得到我用来生成word的文本(这个你们可以忽略)
(2)生成word、设置页边距、设置页脚(页码),设置页码(文本)

一、解析html

Document doc = Jsoup.parseBodyFragment(contents);
Element body = doc.body();
Elements es = body.getAllElements();

二、循环Elements获取我需要的html标签

boolean tag = false;
for (Element e : es) {
    //跳过第一个(默认会把整个对象当做第一个)
    if(!tag) {
        tag = true;
        continue;
    }
    //创建段落:生成word(核心)
    createXWPFParagraph(docxDocument,e);
}

三、生成段落

/**
 * 构建段落
 * @param docxDocument
 * @param e
 */
public static void createXWPFParagraph(XWPFDocument docxDocument, Element e){
    XWPFParagraph paragraph = docxDocument.createParagraph();
    XWPFRun run = paragraph.createRun();
    run.setText(e.text());
    run.setTextPosition(35);//设置行间距

    if(e.tagName().equals("titlename")){
        paragraph.setAlignment(ParagraphAlignment.CENTER);//对齐方式

        run.setBold(true);//加粗
        run.setColor("000000");//设置颜色--十六进制
        run.setFontFamily("宋体");//字体
        run.setFontSize(24);//字体大小

    }else if(e.tagName().equals("h1")){
        addCustomHeadingStyle(docxDocument, "标题 1", 1);
        paragraph.setStyle("标题 1");

        run.setBold(true);
        run.setColor("000000");
        run.setFontFamily("宋体");
        run.setFontSize(20);
    }else if(e.tagName().equals("h2")){
        addCustomHeadingStyle(docxDocument, "标题 2", 2);
        paragraph.setStyle("标题 2");

        run.setBold(true);
        run.setColor("000000");
        run.setFontFamily("宋体");
        run.setFontSize(18);
    }else if(e.tagName().equals("h3")){
        addCustomHeadingStyle(docxDocument, "标题 3", 3);
        paragraph.setStyle("标题 3");

        run.setBold(true);
        run.setColor("000000");
        run.setFontFamily("宋体");
        run.setFontSize(16);
    }else if(e.tagName().equals("p")){
        //内容
        paragraph.setAlignment(ParagraphAlignment.BOTH);//对齐方式
        paragraph.setIndentationFirstLine(WordUtil.ONE_UNIT);//首行缩进:567==1厘米

        run.setBold(false);
        run.setColor("001A35");
        run.setFontFamily("宋体");
        run.setFontSize(14);
        //run.addCarriageReturn();//回车键
    }else if(e.tagName().equals("break")){
        paragraph.setPageBreak(true);//段前分页(ctrl+enter)
    }
}

四、设置页边距

/**
* 设置页边距 (word中1厘米约等于567)
* @param document
* @param left
* @param top
* @param right
* @param bottom
*/
public static void setDocumentMargin(XWPFDocument document, String left,String top, String right, String bottom) {
CTSectPr sectPr = document.getDocument().getBody().addNewSectPr();
CTPageMar ctpagemar = sectPr.addNewPgMar();
if (StringUtils.isNotBlank(left)) {
  ctpagemar.setLeft(new BigInteger(left));
}
if (StringUtils.isNotBlank(top)) {
  ctpagemar.setTop(new BigInteger(top));
}
if (StringUtils.isNotBlank(right)) {
  ctpagemar.setRight(new BigInteger(right));
}
if (StringUtils.isNotBlank(bottom)) {
  ctpagemar.setBottom(new BigInteger(bottom));
}
}

五、创建页眉

/**
 * 创建默认页眉
 *
 * @param docx XWPFDocument文档对象
 * @param text 页眉文本
 * @return 返回文档帮助类对象,可用于方法链调用
 * @throws XmlException XML异常
 * @throws IOException IO异常
 * @throws InvalidFormatException 非法格式异常
 * @throws FileNotFoundException 找不到文件异常
 */
public static void createDefaultHeader(final XWPFDocument docx, final String text){
    CTP ctp = CTP.Factory.newInstance();
    XWPFParagraph paragraph = new XWPFParagraph(ctp, docx);
    ctp.addNewR().addNewT().setStringValue(text);
    ctp.addNewR().addNewT().setSpace(SpaceAttribute.Space.PRESERVE);
    CTSectPr sectPr = docx.getDocument().getBody().isSetSectPr() ? docx.getDocument().getBody().getSectPr() : docx.getDocument().getBody().addNewSectPr();
    XWPFHeaderFooterPolicy policy = new XWPFHeaderFooterPolicy(docx, sectPr);
    XWPFHeader header = policy.createHeader(STHdrFtr.DEFAULT, new XWPFParagraph[] { paragraph });
    header.setXWPFDocument(docx);
}}

六、创建页脚

/**
 * 创建默认的页脚(该页脚主要只居中显示页码)
 *
 * @param docx
 *            XWPFDocument文档对象
 * @return 返回文档帮助类对象,可用于方法链调用
 * @throws XmlException
 *             XML异常
 * @throws IOException
 *             IO异常
 */
public static void createDefaultFooter(final XWPFDocument docx) {
    // TODO 设置页码起始值
    CTP pageNo = CTP.Factory.newInstance();
    XWPFParagraph footer = new XWPFParagraph(pageNo, docx);
    CTPPr begin = pageNo.addNewPPr();
    begin.addNewPStyle().setVal(STYLE_FOOTER);
    begin.addNewJc().setVal(STJc.CENTER);
    pageNo.addNewR().addNewFldChar().setFldCharType(STFldCharType.BEGIN);
    pageNo.addNewR().addNewInstrText().setStringValue("PAGE   \\* MERGEFORMAT");
    pageNo.addNewR().addNewFldChar().setFldCharType(STFldCharType.SEPARATE);
    CTR end = pageNo.addNewR();
    CTRPr endRPr = end.addNewRPr();
    endRPr.addNewNoProof();
    endRPr.addNewLang().setVal(LANG_ZH_CN);
    end.addNewFldChar().setFldCharType(STFldCharType.END);
    CTSectPr sectPr = docx.getDocument().getBody().isSetSectPr() ? docx.getDocument().getBody().getSectPr() : docx.getDocument().getBody().addNewSectPr();
    XWPFHeaderFooterPolicy policy = new XWPFHeaderFooterPolicy(docx, sectPr);
    policy.createFooter(STHdrFtr.DEFAULT, new XWPFParagraph[] { footer });
}

七、自定义标题样式(这个在我另一篇word基础中也有提及)

/**
 * 增加自定义标题样式。这里用的是stackoverflow的源码
 *
 * @param docxDocument 目标文档
 * @param strStyleId 样式名称
 * @param headingLevel 样式级别
 */
private static void addCustomHeadingStyle(XWPFDocument docxDocument, String strStyleId, int headingLevel) {

    CTStyle ctStyle = CTStyle.Factory.newInstance();
    ctStyle.setStyleId(strStyleId);

    CTString styleName = CTString.Factory.newInstance();
    styleName.setVal(strStyleId);
    ctStyle.setName(styleName);

    CTDecimalNumber indentNumber = CTDecimalNumber.Factory.newInstance();
    indentNumber.setVal(BigInteger.valueOf(headingLevel));

    // lower number > style is more prominent in the formats bar
    ctStyle.setUiPriority(indentNumber);

    CTOnOff onoffnull = CTOnOff.Factory.newInstance();
    ctStyle.setUnhideWhenUsed(onoffnull);

    // style shows up in the formats bar
    ctStyle.setQFormat(onoffnull);

    // style defines a heading of the given level
    CTPPr ppr = CTPPr.Factory.newInstance();
    ppr.setOutlineLvl(indentNumber);
    ctStyle.setPPr(ppr);

    XWPFStyle style = new XWPFStyle(ctStyle);

    // is a null op if already defined
    XWPFStyles styles = docxDocument.createStyles();

    style.setType(STStyleType.PARAGRAPH);
    styles.addStyle(style);

}

八、设置页码大小及纸张方向

/**
 * 设置页面大小及纸张方向 landscape横向
 * @param document
 * @param width
 * @param height
 * @param stValue
 */
public void setDocumentSize(XWPFDocument document, String width,String height, STPageOrientation.Enum stValue) {
    CTSectPr sectPr = document.getDocument().getBody().addNewSectPr();
    CTPageSz pgsz = sectPr.isSetPgSz() ? sectPr.getPgSz() : sectPr.addNewPgSz();
    pgsz.setH(new BigInteger(height));
    pgsz.setW(new BigInteger(width));
    pgsz.setOrient(stValue);
}

九、效果展示

java使用POI操作XWPFDocument 生成Word实战(一)

java使用POI操作XWPFDocument 生成Word实战(一)

java使用POI操作XWPFDocument 生成Word实战(一)

java使用POI操作XWPFDocument 生成Word实战(一)

十、demo源码及生成的word文件(相应的jar包大家可以去阿里的maven仓库下载)

demo:https://pan.baidu.com/s/1jHFLniI

java使用POI操作XWPFDocument 生成Word实战(一)

Original: https://www.cnblogs.com/unruly/p/7552998.html
Author: 福尔摩狼
Title: java使用POI操作XWPFDocument 生成Word实战(一)

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/579640/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • ANTLR初探

    ANTLR初探 1.下载ANTLR放在安装目录下 地址:https://www.antlr.org/download/index.html D:\Dev\SrcCode\antlr…

    Java 2023年6月5日
    062
  • 堆排序获取TopN

    package com.zjl.tool.sort; /** * 求前面的最大K个…

    Java 2023年6月16日
    069
  • 我的成长记1:手把手教你如何画出令人称赞的图(程序员必读)

    画一张好图的意义? 作为程序员的你,你经常做的除了起给变量和类起名字、另一就是画图了。抛开起名字这个令人头疼的问题,画图对我们来说是一个表达想法非常不错的方法。 因为画图可以清晰的…

    Java 2023年6月5日
    080
  • 每天代码量多少正常?

    关于程序员每天代码量的讨论,众说纷纭。我个人觉得需要根据具体情况而定。 如果你刚实习,或刚步入工作不久,上司一般都会交给你一些简单的功能实现,这时候一般都含有大量简单而重复或者说类…

    Java 2023年6月13日
    080
  • 面向对象2(Java)

    该露的露,该藏的藏,我们的程序设计要追求”高内聚,低耦合”: 高内聚:类的内部数据操作细节自己完成,不允许外部干涉 低耦合:仅暴露少量的方法给外部使用 封装…

    Java 2023年6月9日
    081
  • 初始Activiti

    工作流,简单的理解就是工作流程,工作流在我们日常生活中无处不在,例如说:员工请假,首先需要提交请假申请,然后提交的申请转到上级领导手里,领导检查过后并同意,最后通知员工领导同意该请…

    Java 2023年6月16日
    073
  • 多线程与高并发(五)—— 源码解析 ReentrantLock

    一、前言 ReentrantLock 是基于 AQS 实现的同步框架,关于 AQS 的源码在 这篇文章 已经讲解过,ReentrantLock 的主要实现都依赖AQS,因此在阅读本…

    Java 2023年6月9日
    071
  • 【力扣】872. 叶子相似的树

    请考虑一棵二叉树上所有的叶子,这些叶子的值按从左到右的顺序排列形成一个 叶值序列 。 举个例子,如上图所示,给定一棵叶值序列为 (6, 7, 4, 9, 8) 的树。 如果有两棵二…

    Java 2023年6月8日
    089
  • 2022最新版SSM源码分析:一套教程助你深入理解底层原理,提高核心竞争力!

    众所周知SSM源码分析教程里面包括Mybatis、Spring以及SpringMVC这三个经典的开源框架的源码分析。我们编程人员技术提升逃不过的一个重要方式就是阅读和理解优秀开源项…

    Java 2023年6月9日
    079
  • Spring源码分析 之浅谈设计模式

    一直想专门写个Spring源码的博客,工作了,可以全身性的投入到互联网行业中。虽然加班很严重,但是依然很开心。趁着凌晨有时间,总结总结。 首先spring,相信大家都很熟悉了。 1…

    Java 2023年5月30日
    046
  • 【java】BigDecimal大于等于/小于等于/小于/大于/等于 比较器工具方法

    BigDecimal大于等于/小于等于/小于/大于/等于 比较器工具方法 public static void main(String[] args) { BigDecimal s…

    Java 2023年5月29日
    071
  • 设置 java -jar 的进程显示名称

    我们经常会在Linux服务器上部署我们的java程序,总会使用 的命令在后台运行程序,这样运行后带来的问题就是,当我们想看相应的java进程时,使用jps命令,java进程只会显示…

    Java 2023年6月16日
    053
  • 短信接口防盗刷解决方案

    在Web开发中,总有一些接口需要暴露在用户认证前访问,短信发送接口特别是短信验证码注册接口便是其中典型的一类,这类接口具有如下特点: 流量在用户认证之前 流量在用户认证之前,意味着…

    Java 2023年6月6日
    085
  • 60行从零开始自己动手写FutureTask是什么体验?

    在并发编程当中我们最常见的需求就是启动一个线程执行一个函数去完成我们的需求,而在这种需求当中,我们常常需要函数有返回值。比如我们需要同一个非常大的数组当中数据的和,让每一个线程求某…

    Java 2023年6月8日
    076
  • dos命令项目创建、编译、执行与jar包生成

    以e盘为例,进入dos环境下,切换到e盘,创建myproject,在其下分别创建source与classes文件夹,source放源代码,classes放编译后的类文件。切换到so…

    Java 2023年6月5日
    088
  • IDEA使用JDBC链接MySql(java编程)

    1、在Maven的pom.xml文件中引入MySql的驱动 2、idea(版本:2021.2.2)JDBC链接MySql数据库 3、编写JDBC代码 : Original: htt…

    Java 2023年6月7日
    059
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球