POI 操作word
- 工作小总结
- 时间:2018-09-25 11:44
- 4729人已阅读
简介
关于POI操作word的基础知识在这个博客(http://elim.iteye.com/blog/2049110)中有非常清晰的解释,在这里我就不多解释了 本文研究的内容就是 XWPFParagraph:代表一个段落XWPFRun:代表具有相同属性的一段文本大家都知道在设计模式中有个构造器模式,用于那些拥有很多属性但是有些属性可选设置的对象的生成。笔者觉得段落和文本的构建能很好
🔔🔔🔔好消息!好消息!🔔🔔🔔
有需要的朋友👉:联系凯哥
关于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厘米≈567 private 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 XWPFRun for (int i = 1; i < lines.length; i++) { // add break and insert new text run.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"); } } }
public static CTPPr getPrOfParagraph(XWPFParagraph p) { CTPPr pPr = null; if (p.getCTP() != null) { if (p.getCTP().getPPr() != null) { pPr = p.getCTP().getPPr(); } else { pPr = p.getCTP().addNewPPr(); } } return pPr; }
文本构建器大体上与段落构建器类似,基本上能满足大多数操作。
以后有时间会研究操作table,这个是重点。加油!
测试结果
备注:因为只是贴出部分代码,其中有两个工具方法未给出,全部代码在github可以看到(https://github.com/jadezhang123/learning/blob/master/apple/src/main/java/own/jadezhang/learning/apple/utils/WordHolder.java)