前语

产品期望完成【公函办理】其间发文拟文一块内容,用户上传正文(word),再挑选不同套红模板,最终拼接为一个对外发文,的公函格局。

根据上次运用vue完成在线修正功用,产品不太满足,从头学习java怎么操作word文档,之前地址:(vue运用Tinymce富文本模拟在线word文档)/post/723665…

终究作用

有两个文件test1.docx (作为红头模板)和test2.docx(作为正文);期望完成作用:用户挑选红头模板加上自己写的正文内容,终究生成可修正的word文档。

create_table.docx 兼并之后终究作用“

java使用apache poi操作word文档

test1.docx 红头模板:

java使用apache poi操作word文档

test2.docx 正文(用户编撰上传的内容):

java使用apache poi操作word文档

预备阶段

技术选型

  1. docx4j:一个用 文档的 Java 库,具有杰出的文档兼并功用。
  2. JODConverter:一个不依靠于 OpenOffice/LibreOffice 的 Java 库,能够协助开发者将 Office 文档转换成 PDF、HTML、XHTML、ODF 等格局,并支撑兼并 Word 文档。
  3. Aspose.Words for Java:一个商业级的文档处理库,支撑多种文档格局的处理,包括 Word、PDF、HTML 等,并且支撑兼并 Word 文档。
  4. FreeMarker:一个模板引擎库,能够用于制造 Word 文档模板,然后运用 Java 代码生成文档。
  5. Apache POI: 是一个开源的 Java 库,能够用来读写 Microsoft Office 文档,包括 Word、Excel、PowerPoint 等各种格局。它是 Apache 软件基金会的一部分,最新版别是 5.0.0。

如标题所示,终究采用Apache POI来完成这个功用首要原因:

  1. 读取和创立 Microsoft Office 文档,包括 Word、Excel、PowerPoint 等多种格局。
  2. 支撑访问和修正文档的一切元素,比方文本、款式、图表、格局等。
  3. 供给丰厚的工具类和办法,能够方便地进行文档操作,比方把文本转换成 HTML、从 Excel 中读取数据、兼并 Word 文档等。
  4. 支撑不同版别的 Office 文档格局,包括旧版别和新版别。
  5. 支撑批量处理很多文档,提高了文档处理的效率。

首要是对于我这种初学者来说是十分友好的,太复杂玩不转。Apache POI 的运用十分简略,只需增加它的 jar 包到项目中,并调用相应的 API 即可完成文档读写。一起,Apache POI 供给了丰厚的文档和官方网站上的文档也很具体。

功用设计思路

  1. 创立一个空的 Word 文档作为兼并后的文档。

  2. 读取要兼并的 Word 文档(test1.doxc、test2.docx),并将它们的内容仿制到兼并后的文档中。能够运用 Apache POI 中的 XWPFDocument 类来读写 Word 文档。

  3. 保存兼并后的文档。运用 XWPFDocument 类的 write(OutputStream out) 办法将文档保存到本地文件或输出流中。

功用完成

Apache POI,分别为 Word、Excel、PowerPoint 等各种格局供给不同的类办法,我们需求操作Word文档的功用,所以运用(Java API for Microsoft Documents)中的XWPFDocument类,完成文档兼并功用。

收拾不同格局文档操作类

  1. HSSF: MS-Excel 97-2003(.xls),根据BIFF8格局的JAVA接口。
  2. XSSF:MS-Excel 2007+(.xlsx),根据OOXML格局的JAVA接口。
  3. HWPF: MS-Word 97-2003(.doc),根据BIFF8格局的JAVA接口。只支撑.doc文件简略的操作,读写能力有限。本API为POI项目早期开发,很不幸的 是首要担任HWPF模块开发的工程师-"Ryan Ackley"现已脱离Apache组织,现在该模块没有人维护、更新、完善。
  4. XWPF:MS-Word 2007+(.docx),根据OOXML格局的JAVA接口。较HWPF功用完善。

注意:word文档现在有两种不同格局,一种是以doc完毕的,另一种以docx完毕,本次功用首要解说docx格局文档操作,doc格局文档调用的类和函数HWPF开头。

两者差异:doc是Word2007及以下版的文件扩展名,而docx是Word2007及以上版别的文件扩展名,docx版别兼容性较高,并且比doc文件所占用空间更小。

引入依靠

在pom.xml文件中引入maven依靠,

        <!-- WordToHtml .doc .odcx  poi  -->
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-scratchpad</artifactId>
            <version>4.1.2</version>
        </dependency>
        <!-- 操作excel的库 注意版别保持一致 poi poi-ooxml  poi-scratchpad -->
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>4.1.2</version>
        </dependency>
        <!--poi-ooxml和*poi-ooxml-schemas*是poi对2007及以上版别的扩大。-->
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml-schemas</artifactId>
            <version>4.1.2</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.apache.poi/poi-ooxml -->
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>4.1.2</version>
        </dependency>
示例代码

简化全体流程,创立两个word文件test1.docx和test2.docx。将下列file对应的文件途径换成自己创立的文件途径创,建单个java文件(带main),直接运行main办法输出creat_table.docx文件。 先上代码,再进行解说:

package org.ssssssss.magicboot;
import org.apache.poi.xwpf.usermodel.*;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.List;
public class WordDocumentTest {
    public static void main(String[] args) throws Exception
    {
        //获取文件转io流
        File file1 = new File("D:/IDM/test1.docx");
        File file2 = new File("D:/IDM/test2.docx");
        FileInputStream fis1 = new FileInputStream(file1);
        FileInputStream fis2 = new FileInputStream(file2);
        //终究文件输出的途径
        FileOutputStream out = new FileOutputStream(new File("D:/IDM/create_table.docx"));
        //转为word文档元素
        XWPFDocument dcx1 = new XWPFDocument(fis1);
        XWPFDocument dcx2 = new XWPFDocument(fis2);
        //创立一个新的文档
        XWPFDocument document= new XWPFDocument();
        //将榜首个文档元素仿制新创立的文档中;
        document = dcx1;
        //换行 document.createParagraph().createRun().addBreak();
        //将第二个docx内容增加到新创立的文档中
        mergeParagraphs(dcx2.getParagraphs(), document);
        //完毕关闭io流
        document.write(out);
        out.close();
        fis1.close();
        fis2.close();
        System.out.println("create_table document written success.");
    }
    // 兼并文本阶段
    private static void mergeParagraphs(List<XWPFParagraph> paragraphs, XWPFDocument outDoc) {
        for (XWPFParagraph para : paragraphs) {
            XWPFParagraph newPara = outDoc.createParagraph();
            newPara.getCTP().setPPr(para.getCTP().getPPr());
            //判断是否是文本、阶段、图片 //.getRPr() para.tables !=null ,iruns 获取图片
            for (XWPFRun run : para.getRuns()) {
                XWPFRun newRun = newPara.createRun();
                newRun.getCTR().setRPr(run.getCTR().getRPr());
                newRun.setText(run.getText(0));
            }
        }
    }
代码解释

完成流程首要看代码中的注释,包括以下几个过程

  1. 获取文件转io流
  2. 将io流转为word文档元素(XWPFDocument)
  3. 创立一个新的文档
  4. 将榜首个文档元素仿制新创立的文档中
  5. 将第二个docx内容增加到新创立的文档中
  6. 输出新文档,关闭io流

核心要点将第二个docx内容增加到新创立的文档中封装mergeParagraphs办法,在这个办法中传入了两个参数(List paragraphs, XWPFDocument outDoc) 其间List<XWPFParagraph> paragraphs = dcx2.getParagraphs() 意思是将dcx2文档一切阶段取出来用一个数组寄存,再进行循环阶段;经过XWPFParagraph newPara = outDoc.createParagraph();给新的文档创立一个新的阶段;给新的阶段增加对应的款式newPara.getCTP().setPPr(para.getCTP().getPPr());最终由于阶段中会区分不同的XWPFRun再进行循环设置文本的字体、巨细、色彩、加粗、斜体、下划线等格局。 官方api介绍

java使用apache poi操作word文档

java使用apache poi操作word文档

方才对XWPFRun没有进行很好的解释,这儿从头举例说明下,例如以下标红的阶段

java使用apache poi操作word文档
依照正常了解这一个阶段内容应该是一个东西,其实在XWPF中会区分为不同的XWPFRun,运用idea打断点检查数据

java使用apache poi操作word文档
能够看出它将一段文字区分为不同模块,为什么会这样,在一段文字中也存在不同的差异,例如文字的字体,像下图中“根据”“2023”归于不同的字体,所以会区分为不同的XWPFRun,了解这个概念后同理明白为什么一个阶段会区分为29模块

java使用apache poi操作word文档

java使用apache poi操作word文档

相关函数

在前面其完成已完成榜首个模块终究作用的docx文档兼并的功用,所以在这个模块解说在完成这个过程中记载有意思的内容。

XWPFRun(文本阶段)

接着上面讲XWPFRun这个函数,XWPFRun用于在 Word 文档中增加或修正单个本 Run 或 Run 中的文字格局。它是文本阶段(XWPFParagraph)中的最小单元,用于精密操控文本的格局和款式。能够运用 XWPFRun 类的各种办法来设置文本的字体、巨细、色彩、加粗、斜体、下划线等格局。 下列是在运用过程中记载的一些特点,以及这些特点对应能够设置的格局注释。

    XWPFRun run = firstParagraph.createRun();
                XWPFRun tempRun = xwpfRuns.get(i);
                //默许:宋体(wps)/等线(office2016) 5号 两端对齐 单倍距离
                run.setText(tempRun.text());
                //加粗
                run.setBold(tempRun.isBold());
                //我也不知道这个特点做啥的
                run.setCapitalized(tempRun.isCapitalized());
                //设置色彩--十六进制
                run.setColor(tempRun.getColor());
                //这个特点报错
                run.setCharacterSpacing(tempRun.getCharacterSpacing());
                //浮雕字体----作用和印记(悬浮阴影)类似
                run.setEmbossed(tempRun.isEmbossed());
                //双删去线
                run.setDoubleStrikethrough(tempRun.isDoubleStrikeThrough());
                run.setEmphasisMark(tempRun.getEmphasisMark().toString());
                //字体,//字体,范围----作用不详
                run.setFontFamily(tempRun.getFontFamily());
                //字体巨细,没有设置默许是-1,
                if(tempRun.getFontSize() != -1){
                    run.setFontSize(tempRun.getFontSize());
                }
                //印迹(悬浮阴影)---作用和浮雕类似
                run.setImprinted(tempRun.isImprinted());
                //斜体(字体歪斜)
                run.setItalic(tempRun.isItalic());
                //字距调整----这个好像没有作用
                run.setKerning(tempRun.getKerning());
                //阴影---略微有点作用(阴影不明显)
                run.setShadow(tempRun.isShadowed());
                //小型股------作用不清楚
                run.setSmallCaps(tempRun.isSmallCaps());
                //单删去线(抛弃)
                run.setStrike(tempRun.isStrike());
                //单删去线(新的替换Strike)
                run.setStrikeThrough(tempRun.isStrikeThrough());
                //下标(吧当时这个run变成下标)---枚举
                run.setSubscript(tempRun.getSubscript());
                //设置两行之间的行距离
                run.setTextPosition(tempRun.getTextPosition());
                //各种类型的下划线(枚举)
                run.setUnderline(tempRun.getUnderline());
                run.setVerticalAlignment(tempRun.getVerticalAlignment().toString());
                run.setVanish(tempRun.isVanish());
                run.setUnderlineThemeColor(tempRun.getUnderlineColor());
                run.setUnderlineColor(tempRun.getUnderlineColor());
                run.setTextScale(tempRun.getTextScale());
                run.setTextPosition(tempRun.getTextPosition());
                run.setTextHighlightColor(tempRun.getTextHightlightColor().toString());
//                run.setStyle(tempRun.gets); 没找到这个特点
                run.setLang(tempRun.getLang());
XWPFParagraph(阶段)

XWPFParagraph 是 Apache POI 库中 XWPF 模块的一部分,用于创立或修正 Word 文档中的阶段。它能够增加不同的文本格局,并且能够增加图片、表格、超链接等内容。XWPFParagraph 类能够操控阶段的款式和格局,包括字体、字号、行距、首行缩进、对齐办法等。能够运用 XWPFParagraph 类的各种办法来设置阶段的格局和款式。

    常用办法:
    //创立一个新的 XWPFRun 对象,用于在阶段中增加文本或修正文本格局。
    createRun()
    //设置阶段的对齐办法,align 参数能够是 LEFT、CENTER、RIGHT、JUSTIFY 等值。
    setAlignment(ParagraphAlignment align)
    //设置阶段的行距和行距规矩,lineSpacing 参数是行距巨细(以磅为单位),lineSpacingRule 参数能够是 EXACT、AT_LEAST、AUTO 等值。
    setSpacingBetween(int lineSpacing, LineSpacingRule lineSpacingRule)
    //设置阶段的左缩进巨细(以磅为单位)。
    setIndentationLeft(int indentation)
    //设置阶段的右缩进巨细(以磅为单位)。
    setIndentationRight(int indentation)
    //设置阶段的编号 ID。
    setNumID(BigInteger numId)
    //设置阶段的编号格局,numFmt 参数能够是 DECIMAL、LOWERCASE_LETTER、UPPERCASE_LETTER 等值。
    setNumFmt(NumberFormat numFmt)
    //在阶段中增加图片,pictureType 参数是图片类型,filename 参数是图片文件名,width 和 height 参数是图片宽度和高度。
    createPicture(XWPFRun run, int pictureType, String filename, int width, int height)
    其他办法:
    //指定应显现在左面页面指定段周围的鸿沟。
    setBorderBottom(Borders.APPLES); 
    //指定应显现在下边页面指定段周围的鸿沟。
    setBorderLeft(Borders.APPLES);
    //指定应显现在右侧的页面指定段周围的鸿沟。
    setBorderRight(Borders.ARCHED_SCALLOPS);
    //指定应显现上方一组有相同的一组段鸿沟设置的阶段的鸿沟。这几个是对阶段之间的格局的统一,相当于格局刷
    setBorderTop(Borders.ARCHED_SCALLOPS);
    //---正文宽度会略微变窄 
    p1.setFirstLineIndent(99);
    //---阶段的对齐办法 1左 2中 3右 4往上 左 不可写0和负数
    p1.setFontAlignment(1);
    //---首行缩进,指定额定的缩进,应适用于父段的榜首行。
    p1.setIndentationFirstLine(400);
    //---首行行进,指定的缩进量,应经过榜首行回到开端的文本流的方向上移动缩进从父段的榜首行中删去。
    p1.setIndentationHanging(400);
    //---整段右移
    p1.setIndentFromLeft(400);
    //--此办法供给了款式的阶段,这十分有用。
    p1.setStyle("");
    //--此元素指定是否顾客应中断超越一行的文本范围,经过打破这个词 (打破人物等级) 的两行或经过移动到下一行 (在词汇层面上打破) 这个词的拉丁文字。
    p1.setWordWrapped(true);
    //---指定的文本的垂直对齐办法将使用于此阶段中的文本 
    p1.setVerticalAlignment(TextAlignment.CENTER);
    //--指定行之间的距离怎么核算存储在行特点中。 
    p1.setSpacingLineRule(LineSpacingRule.AT_LEAST);
    //--指定应增加在此线单位在文档中的阶段的榜首行之前的距离。
    p1.setSpacingBeforeLines(6);  
    //--指定应增加上面这一段文档中肯定单位中的榜首行的距离。
    p1.setSpacingBefore(6); 
    //--指定应增加在此线单位在文档中的阶段的最终一行之后的距离。 
    p1.setSpacingAfterLines(6);
    //--指定应增加在文档中肯定单位这一段的最终一行之后的距离。
    p1.setSpacingAfter(6); 
    //--指定当渲染此分页视图中的文档,这一段的内容都呈现在文档中的新页的开端。
    p1.setPageBreak(true);

其他功用

刚在展示活动内容都是根据本身的需求写小demo,实践项目远远不止这些内容,其间仍是存在不足之处,例如word中的表格、图片都是需求单独处理,表格有个专类别XWPFTable;图片也有XWPFPictureData、 XWPFPicture

java使用apache poi操作word文档

java使用apache poi操作word文档
java使用apache poi操作word文档

学习参阅

Apache POI 官方网站供给了完好的 API 文档:poi.apache.org/apidocs/dev…

Apache POI 的 GitHub 库房中检查示例代码和文档:github.com/apache/poi

Java POI 生成Word文档:blog.csdn.net/qq_34755766…

Apache POI 中文版download.csdn.net/download/qq…

官方网站上的示例代码和文档也十分具体,学习 Apache POI 最好的办法是结合实践使用进行学习,一起多查阅相关的文档和例子,不断尝试编写代码,才干融会贯通逐步把握运用技巧。