关于POI 操作word的基础知识在这个博客(http://elim.iteye.com/blog/2049110)中有非常清晰的解释,在这里我就不多解释了
本文研究的内容就是
XWPFParagraph:代表一个段落

XWPFRun:代表具有相同属性的一段文本

大家都知道在设计模式中有个构造器模式,用于那些拥有很多属性但是有些属性可选设置的对象的生成。笔者觉得段落和文本的构建能很好运用此种模式。

首先是段落构建器

    //段落构建器public class XWPFParagraphBuilder {//常量,在文档中定义长度和高度的单位private static final int PER_LINE = 100;//每个字符的单位长度private static final int PER_CHART = 100;//1厘米≈567private static final int PER_CM = 567;//每一磅的单位长度private static final int PER_POUND = 20;//行距单位长度private static final int ONE_LINE = 240;private XWPFParagraph paragraph = null;private CTPPr pPr = null;//保存通用段落属性引用,方便复用private Map<String, CTPPr> savedPPr = null;//设定间距的对象private CTSpacing pSpacing = null;//设定缩进的对象private CTInd pInd = null;public XWPFParagraphBuilder init(XWPFDocument document) {return init(document.createParagraph());}public XWPFParagraphBuilder init(XWPFParagraph paragraph) {if (paragraph == null) {throw new IllegalArgumentException("the paragraph should not be null");}this.paragraph = paragraph;pPr = getPrOfParagraph(paragraph);return this;}//设置段落对齐方式public XWPFParagraphBuilder align(ParagraphAlignment pAlign, TextAlignment vAlign) {ensureInit();if (pAlign != null) {paragraph.setAlignment(pAlign);}if (vAlign != null) {paragraph.setVerticalAlignment(vAlign);}return this;}//初始化段落间距属性,在设置各段落间距前调用public XWPFParagraphBuilder initSpacing() {ensureInit();pSpacing = pPr.getSpacing() != null ? pPr.getSpacing() : pPr.addNewSpacing();return this;}//设置段前和段后间距,以磅为单位public XWPFParagraphBuilder spaceInPound(double before, double after) {ensureInit();if (pSpacing == null) {initSpacing();}pSpacing.setBefore(BigInteger.valueOf((long) (before * PER_POUND)));pSpacing.setAfter(BigInteger.valueOf((long) (after * PER_POUND)));return this;}//设置段前和段后间距,以行为单位public XWPFParagraphBuilder spaceInLine(double beforeLines, double afterLines) {ensureInit();if (pSpacing == null) {initSpacing();}pSpacing.setBeforeLines(BigInteger.valueOf((long) (beforeLines * PER_LINE)));pSpacing.setAfterLines(BigInteger.valueOf((long) (afterLines * PER_LINE)));return this;}//设置段落行距public XWPFParagraphBuilder lineSpace(double value, STLineSpacingRule.Enum spaceRule) {ensureInit();if (pSpacing == null) {initSpacing();}int unit;if (spaceRule == null) {spaceRule = STLineSpacingRule.AUTO;}if (spaceRule.intValue() == STLineSpacingRule.INT_AUTO) {//当行距规则为多倍行距时,单位为行,且最小为0.06行unit = ONE_LINE;if (value < 0.06) {value = 0.06;}} else {//当行距规则为固定值或最小值时,单位为磅,且最小为0.7磅unit = PER_POUND;if (value < 0.7) {value = 0.7;}}pSpacing.setLine(BigInteger.valueOf((long) (value * unit)));pSpacing.setLineRule(spaceRule);return this;}public XWPFParagraphBuilder initInd() {ensureInit();pInd = pPr.getInd() != null ? pPr.getInd() : pPr.addNewInd();return this;}//设置段落缩进,以厘米为单位; 悬挂缩进高于首行缩进;右侧缩进高于左侧缩进public XWPFParagraphBuilder indentInCM(double firstLine, double hanging, double right, double left) {ensureInit();if (pInd == null) {initInd();}if (firstLine != 0) {pInd.setFirstLine(BigInteger.valueOf((long) (firstLine * PER_CM)));}if (hanging != 0) {pInd.setHanging(BigInteger.valueOf((long) (hanging * PER_CM)));}if (right != 0) {pInd.setRight(BigInteger.valueOf((long) (right * PER_CM)));}if (left != 0) {pInd.setLeft(BigInteger.valueOf((long) (left * PER_CM)));}return this;}//设置段落缩进,以字符为单位; 悬挂缩进高于首行缩进;右侧缩进高于左侧缩进public XWPFParagraphBuilder indentInChart(int firstLine, int hanging, int left, int right) {ensureInit();if (pInd == null) {initInd();}if (firstLine != 0) {pInd.setFirstLineChars(BigInteger.valueOf((long) (firstLine * PER_CHART)));}if (hanging != 0) {pInd.setHangingChars(BigInteger.valueOf((long) (hanging * PER_CHART)));}if (right != 0) {pInd.setRightChars(BigInteger.valueOf((long) (right * PER_CHART)));}if (left != 0) {pInd.setLeftChars(BigInteger.valueOf((long) (left * PER_CHART)));}return this;}public XWPFParagraphBuilder savePr(String pPrName) {ensureInit();if (savedPPr == null) {savedPPr = new HashedMap<String, CTPPr>();}savedPPr.put(pPrName, pPr);return this;}public XWPFParagraphBuilder samePrOf(String pPrName) {ensureInit();if (savedPPr != null && savedPPr.containsKey(pPrName)) {return samePrOf(savedPPr.get(pPrName));}return this;}public XWPFParagraphBuilder samePrOf(CTPPr pPr) {ensureInit();if (pPr != null) {paragraph.getCTP().setPPr(pPr);}return this;}public XWPFParagraphBuilder samePrOf(XWPFParagraph otherPra) {ensureInit();paragraph.getCTP().setPPr(getPrOfParagraph(otherPra));return this;}public XWPFParagraph build() {return paragraph;}//确保init方法是第一个调用的,避免出现空指针异常private void ensureInit() {if (this.paragraph == null) {throw new IllegalStateException("the init method must be invoked firstly");}}}

构建器的优点在于能够链式调用
示例:

        //新增一个段前2倍行距段后3倍行距,文本2倍行距的段落XWPFParagraph firstPar = paragraphBuilder.init(document).initSpacing().spaceInLine(2, 3).lineSpace(2, null).build();

如果有一段段落的属性与之前段落相同,你可以在链尾调用savePr(String pPrName),来为保存该属性,并制定名称,当有其他段落要用到次属性时就可以在调用samePrOf(String pPrName)来设定属性避免重复操作。

其中有一点需要注意的是:init方法一定是第一个调用的,不然会出现空指针异常

接下来是文本构建器(思想与段落相同)

 //文本构建器public class XWPFRunBuilder {private XWPFRun run = null;private Map<String, CTRPr> savedRPr;public XWPFRunBuilder init(XWPFParagraph paragraph) {return init(paragraph, false);}public XWPFRunBuilder init(XWPFParagraph paragraph, boolean newLine) {this.run = paragraph.createRun();if (newLine) {run.addBreak();}return this;}/*** insert a new Run in RunArray** @param pos The position at which the new run should be added.*/public XWPFRunBuilder init(XWPFParagraph paragraph, int pos) {this.run = paragraph.insertNewRun(pos);if (this.run == null) {return init(paragraph, false);}return this;}public XWPFRunBuilder init(XWPFRun run) {if (run == null) {throw new IllegalArgumentException("the run should not be null");}this.run = run;return this;}public XWPFRunBuilder content(String content) {ensureInit();if (StringUtils.isNotBlank(content)) {// pRun.setText(content);if (content.contains("\n")) {// System.properties("line.separator")String[] lines = content.split("\n");run.setText(lines[0], 0); // set first line into XWPFRunfor (int i = 1; i < lines.length; i++) {// add break and insert new textrun.addBreak();run.setText(lines[i]);}} else {run.setText(content, 0);}}return this;}//加粗public XWPFRunBuilder bold(boolean bold) {ensureInit();run.setBold(bold);return this;}//斜体public XWPFRunBuilder italic(boolean italic) {ensureInit();run.setItalic(italic);return this;}//删除线public XWPFRunBuilder strike(boolean strike) {ensureInit();run.setStrike(strike);return this;}//字体设置,中文字体、英文字体、字号public XWPFRunBuilder font(String cnFontFamily, String enFontFamily, String fontSize) {ensureInit();CTRPr rPr = getPrOfRun(run);// 设置字体CTFonts fonts = rPr.isSetRFonts() ? rPr.getRFonts() : rPr.addNewRFonts();if (StringUtils.isNotBlank(enFontFamily)) {fonts.setAscii(enFontFamily);fonts.setHAnsi(enFontFamily);}if (StringUtils.isNotBlank(cnFontFamily)) {fonts.setEastAsia(cnFontFamily);fonts.setHint(STHint.EAST_ASIA);}// 设置字体大小CTHpsMeasure sz = rPr.isSetSz() ? rPr.getSz() : rPr.addNewSz();sz.setVal(new BigInteger(fontSize));CTHpsMeasure szCs = rPr.isSetSzCs() ? rPr.getSzCs() : rPr.addNewSzCs();szCs.setVal(new BigInteger(fontSize));return this;}//底纹public XWPFRunBuilder shade(STShd.Enum shdStyle, String shdColor) {ensureInit();CTRPr rPr = getPrOfRun(run);// 设置底纹CTShd shd = rPr.isSetShd() ? rPr.getShd() : rPr.addNewShd();if (shdStyle != null) {shd.setVal(shdStyle);}if (shdColor != null) {shd.setColor(shdColor);shd.setFill(shdColor);}return this;}/*** @param position 字符垂直方向上间距位置; >0:提升; <0:降低;=磅值*2* @return*/public XWPFRunBuilder position(int position) {ensureInit();if (position != 0) {run.setTextPosition(position);}return this;}//字符间距public XWPFRunBuilder space(int spacingValue) {ensureInit();if (spacingValue > 0) {CTRPr rPr = getPrOfRun(run);CTSignedTwipsMeasure measure = rPr.isSetSpacing() ? rPr.getSpacing() : rPr.addNewSpacing();measure.setVal(new BigInteger(String.valueOf(spacingValue)));}return this;}/*** @param verticalAlign SUPERSCRIPT:上标;SUBSCRIPT:下标* @return*/public XWPFRunBuilder verticalAlign(VerticalAlign verticalAlign) {ensureInit();if (verticalAlign != null) {run.setSubscript(verticalAlign);}return this;}//下划线public XWPFRunBuilder underLine(STUnderline.Enum underStyle, String underLineColor) {ensureInit();CTRPr rPr = getPrOfRun(run);CTUnderline udLine = rPr.addNewU();udLine.setVal(underStyle);udLine.setColor(underLineColor);return this;}//高亮public XWPFRunBuilder highLight(STHighlightColor.Enum highStyle) {ensureInit();CTRPr rPr = getPrOfRun(run);if (highStyle != null) {CTHighlight highLight = rPr.isSetHighlight() ? rPr.getHighlight() : rPr.addNewHighlight();highLight.setVal(highStyle);}return this;}public XWPFRunBuilder savePr(String rPrName) {ensureInit();if (savedRPr == null) {savedRPr = new HashedMap<String, CTRPr>();}savedRPr.put(rPrName, getPrOfRun(run));return this;}public XWPFRunBuilder samePrOf(String rPrName) {ensureInit();if (savedRPr != null && savedRPr.containsKey(rPrName)) {return samePrOf(savedRPr.get(rPrName));}return this;}public XWPFRunBuilder samePrOf(CTRPr rPr) {ensureInit();if (rPr != null) {run.getCTR().setRPr(rPr);}return this;}public XWPFRunBuilder samePrOf(XWPFRun otherRun) {ensureInit();run.getCTR().setRPr(getPrOfRun(otherRun));return this;}public XWPFRun build() {return run;}private void ensureInit() {if (this.run == null) {throw new IllegalStateException("the init method must be invoked firstly");}}}

文本构建器大体上与段落构建器类似,基本上能满足大多数操作。

备注:因为只是贴出部分代码,其中有两个工具方法未给出,全部代码在github可以看到(https://github.com/jadezhang123/learning/blob/master/apple/src/main/java/own/jadezhang/learning/apple/utils/WordHolder.java)

以后有时间会研究操作table,这个是重点。加油!
测试结果

POI 操作word相关推荐

  1. java poi 操作word遇到的问题

    java poi 操作word文本,图表,遇到的问题 直接上问题 模板字段匹配问题 图表问题 图表导出 问题:模板找不到对应图表 问题:数据填充后效果不达目标 图表中为零的数值去掉(!!!模板层面解决 ...

  2. 使用poi操作word

    导入依赖 <dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifa ...

  3. 报表技术2(百万数据导入导出,POI操作word)

    POI模板导出,操作word 导出用户详情数据(图片,公式处理) 使用模板导出用户详细信息 使用模板引擎 1.编写模板引擎 2.使用模板引擎 百万数据导出 代码实现: 百万数据导入 步骤分析: 1.自 ...

  4. poi操作word常用操作方法,word工具包

    poi操作word工具类 当前poi版本:3.17,升级版本写法略有差异 新版poi操作方法: - poi-5.2.2 操作word [段落] - poi-5.2.2 操作word [表格] - po ...

  5. poi操作word文档总结

    POI分段落生成纯Word动态模板并导入数据 导出数据,可以用word另存为xml格式的ftl文件,变量用${变量名}表示,然后在类中通过 freemarker去替换变量. 但是怎么导入word数据. ...

  6. 使用poi操作word文档实现套打功能

    使用poi操作word文档实现套打功能 本文目的是为了分享一个实现套打功能,但是不同于简单的word的文本替换而是采用poi对word的文本框就行操作实现的功能: poi中各种jar的说明 套打的实现 ...

  7. poi操作word替换模板向指定位置添加图表

    poi操作word替换模板向指定位置添加图表 首先是引入pom文件 <dependency><groupId>org.apache.poi</groupId>< ...

  8. java word apache poi 操作word模板。

    apache poi 操作word模板. 操作方式: 1.对于固定格,可以遍历格子然后替换其中指定的值例如在要替换的cell写入${example} 这样格式,遍历到之后替换. 2.对于需要增长的表格 ...

  9. poi操作word 2003/doc

    poi操作word 2003/doc HWPFDocument中的要素 maven引用 通过WordExtractor读取文本 通过HWPFDocument读文件 通过HWPFDocument写文件 ...

最新文章

  1. java sip 携带sdp_SIP中的SDP offer/answer交换初探
  2. 30 分钟 git 命令入门
  3. redis 慢日志 slowlog
  4. 如何降低数据中心宕机事件的影响
  5. [Android工具]更新音乐下载软件,MP3音乐无损音乐下载器
  6. 【NOI2013模拟】棋盘游戏
  7. Zynq-7000系统公共资源及特性
  8. 黑马java代码04-05.docx
  9. d3.js 获取当前像素坐标_Cesium开发入门篇 | 06坐标系及坐标变换
  10. 一个10年SEO工作者的35个SEO经验
  11. Python操作文件和目录
  12. java判断字符串中是否含有某个字符串
  13. web.config forms节点中的属性的含义和用途
  14. linux中的 127.0.0.1和0.0.0.0和::
  15. 鸟哥的 Linux 私房菜学习笔记
  16. 机器学习-线性回归scikit-learn
  17. matlab 秩和检验,多个独立样本比较的秩和检验(Kruskal-Wallis H)
  18. Cocoa-专业术语
  19. 2019 Python接口自动化测试框架实战开发(一)
  20. FBA 街机游戏安卓盒子,游戏盒子实现双人对打,四人对打方案

热门文章

  1. Ardupilot源码框架
  2. 微信Windows客户端版本无法打开小程序问题的解决
  3. 对数数学知识回忆(log)
  4. c语言实现计算函数在某点的导数近似值
  5. 帝国cms 7.5 utf8集成百度编辑器完美集成版
  6. input button 光标变为手型
  7. cursor(鼠标手型)属性
  8. mysql篇-sql查询语句-平均分、最高最低分、排序
  9. 代码审计工具简单汇总
  10. Arithmetic Progressions