POI 操作word

關於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");
            }
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199

構建器的優點在於能夠鏈式調用 
示例:

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

如果有一段段落的屬性與之前段落相同,你可以在鏈尾調用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");
            }
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216

文本構建器大體上與段落構建器類似,基本上能滿足大多數操作。

備註:因爲只是貼出部分代碼,其中有兩個工具方法未給出,全部代碼在github可以看到(https://github.com/jadezhang123/learning/blob/master/apple/src/main/java/own/jadezhang/learning/apple/utils/WordHolder.java

以後有時間會研究操作table,這個是重點。加油! 
測試結果

這裏寫圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章