开发者

从入门到实战详解如何使用Apache POI操作Word文档

目录
  • 一、Apache POI简介与环境准备
    • 1. Apache POI组件
    • 2. 添加Maven依赖
    • 3. 核心类介绍
  • 二、创建Word文档
    • 1. 创建简单文档
    • 2. 添加复杂格式
  • 三、操作表格
    • 1. 创建表格
    • 2. 表格样式设置
  • 四、插入图片
    • 五、读取和修改现有文档
      • 1. 读取文档内容
      • 2. 修改现有文档
    • 六、高级功能
      • 1. 页眉页脚设置
      • 2. 目录生成
      • 3. 批注(注释)添加
    • 七、性能优化与最佳实践
      • 1. 大文件处理优化
      • 2. 内存管理
      • 3. 样式重用
    • 八、常见问题与解决方案
      • 1. 中文乱码问题
      • 2. 格式不兼容问题
      • 3. 性能问题
    • 九、总结

      Apache POI是Java生态中最流行的Microsoft Office文档操作库之一,它为Word文档(包括传统的.doc格式和现代的.docx格式)提供了全面的API支持。本文将详细介绍如何使用Apache POI创建、读取和修改Word文档。

      一、Apache POI简介与环境准备

      1. Apache POI组件

      Apache POI包含多个组件用于处理不同Office文档:

      • POI-HwpF:处理.doc格式(Word 97-2003)
      • POI-XWPF:处理.docx格式(Word 2007及以后版本)
      • POI-HSLF:处理PowerPoint
      • POI-HSSF/XSSF:处理Excel

      2. 添加Maven依赖

      <dependency>
          <groupId>org.apache.poi</groupId>
          <artifactId>poi</artifactId>
          <version>5.2.3</version>
      </dependency>
      <dependency>
          <groupId>org.apache.poi</groupId>
          <artifactId>poi-ooXML</artifactId>
          <version>5.2.3</version>
      </dependency>
      

      3. 核心类介绍

      XWPFDocument:代表整个Word文档

      XWPFParagraph:文档中的段落

      XWPFRun:段落中的文本运行(具有相同格式的文本段)

      XWPFTable:表格

      XWPFPicture:图片

      二、创建Word文档

      1. 创建简单文档

      import org.apache.poi.xwpf.usermodel.*;
      
      imporjavascriptt java.io.FileOutputStream;
      import java.io.IOException;
      
      public class SimpleDocumentCreator {
          public static void main(String[] args) throws IOException {
              // 1. 创建空文档
              XWPFDocument document = new XWPFDocument();
              
              // 2. 创建段落
              XWPFParagraph title = document.createParagraph();
              title.setAlignment(ParagraphAlignment.CENTER);
              
              // 3. 创建文本运行并设置样式
              XWPFRun titleRun = title.createRun();
              titleRun.setText("Apache POI示例文档");
              titleRun.setBold(true);
              titleRun.setFontSize(16);
              
              // 4. 添加正文段落
              XWPFParagraph body = document.createParagraph();
              body.setAlignment(ParagraphAlignment.LEFT);
              body.setIndentationFirstLine(600); // 首行缩进
              
              XWPFRun bodyRun = body.createRun();
              bodyRun.setText("这是使用Apache POI创建的Word文档。");
              bodyRun.addBreak(); // 换行
              bodyRun.setText("POI支持丰富的文本格式设置。");
              
              // 5. 保存文档
              try (FileOutputStream out = new FileOutputStream("SimpleDocument.docx")) {
                  document.write(out);
              }
              
              document.close();
              System.out.println("文档创建成功!");
          }
      }
      

      2. 添加复杂格式

      // 创建带格式的段落
      XWPFParagraph styledPara = document.createParagraph();
      styledPara.setAlignment(ParagraphAlignment.BOTH); // 两端对齐
      
      XWPFRun styledRun = styledPara.createRun();
      styledRun.setText("格式丰富的文本:");
      styledRun.setColor("FF0000"); // 红色
      styledRun.setFontFamily("宋体");
      styledRun.addBreak();
      
      // 添加不同格式的文本
      styledRun = styledPara.createRun();
      styledRun.setText("粗体+斜体");
      styledRun.setBold(true);
      styledRun.setItalic(true);
      styledRun.addTab(); // 制表符
      
      styledRun = styledPara.createRun();
      styledRun.setText("下划线");
      styledRun.setUnderline(UnderlinePatterns.SINGLE);
      

      三、操作www.devze.com表格

      1. 创建表格

      // 创建3行4列的表格
      XWPFTable table = document.createTable(3, 4);
      
      // 设置表格宽度
      table.setWidth("100%");
      
      // 填充表头
      XWPFTableRow headerRow = table.getRow(0);
      headerRow.getCell(0).setText("序号");
      headerRow.getCell(1).setText("姓名");
      headerRow.getCell(2).setText("年龄");
      headerRow.getCell(3).setText("部门");
      
      // 填充数据
      for (int i = 1; i < 3; i++) {
          XWPFTableRow row = table.getRow(i);
          row.getCell(0).setText(String.valueOf(i));
          row.getCell(1).setText("员工" + i);
          row.getCell(2).setText(String.valueOf(20 + i));
          row.getCell(3).setText(i % 2 == 0 ? "技术部" : "市场部");
      }
      
      // 合并单元格
      table.getRow(2).getCell(3).setText("备注:所有部门");
      table.addNewColSpan(2, 3, 2); // 合并第3行的第3-4列
      

      2. 表格样式设置

      // 设置表格边框
      CTTblPr tblPr = table.getCTTbl().getTblPr();
      CTBorder border = tblPr.addNewTblBorders();
      border.addNewBottom().setVal(STBorder.SINGLE);
      border.addNewTop().setVal(STBorder.SINGLE);
      border.addNewLeft().setVal(STBorder.SINGLE);
      border.addNewRight().setVal(STBorder.SINGLE);
      border.addNewInsideH().setVal(STBorder.SINGLE);
      border.addNewInsideV().setVal(STBorder.SINGLE);
      
      // 设置表头背景色
      for (XWPFTableCell cell : headerRow.getTableCells()) {
          cell.setColor("D3D3D3"); // 浅灰色背景
      }
      

      四、插入图片

      import org.apache.poi.util.Units;
      
      // 从文件插入图片
      try (FileInputStream is = new FileInputStream("logo.png")) {
          XWPFParagraph imagePara = document.createParagraph();
          imagePara.setAlignment(ParagraphAlignment.CENTER);
          
          XWPFRun imageRun = imagePara.createRun();
          imageRun.addPicture(is, 
                             Document.PICTURE_TYPE_PNG, 
                             "logo.png", 
                             Units.toEMU(200), // 宽度
                             Units.toEMU(100)); // 高度
      }
      
      // 从字节数组插入图片
      byte[] imageData = getImageData(); // 获取图片字节数组的方法
      XWPFRun imageRun = document.createParagraph().createRun();
      imageRun.addPicture(new ByteArrayInputStream(imageData),
                         Document.PICTURE_TYPE_JPEG,
                         "photo.jpg",
                         Units.toEMU(150),
                         Units.toEMU(150));
      

      五、读取和修改现有文档

      1. 读取文档内容

      public void readDocument(String filePath) throws IOException {
          try (FileInputStream fis = new FileInputStream(filePath);
               XWPFDocument document = new XWPFDocument(fis)) {
              
              System.out.println("==== 段落 ====");
              for (XWPFParagraph para : document.getParagraphs()) {
                  System.out.println(para.getText());
              }
              
              System.out.println("\n==== 表格 ====");
              for (XWPFTable table : document.getTables()) {
                  for (XWPFTableRow row : table.getRows()) {
                      for (XWPFTableCell cell : row.getTableCells()) {
                          System.out.print(cell.getText() + "\t");
           编程客栈           }
                      System.out.println();
                  }
              }
          }
      }

      2. 修改现有文档

      public void modifyDocument(String inputPath, String outputPath) throws IOException {
          try (FileInputStream fis = new FileInputStream(inputPath);
               XWPFDocument document = new XWPFDocument(fis)) {
              
              // 修改第一个段落
              XWPFParagraph firstPara = document.getParagraphs().get(0);
              if (firstPara != null) {
                  XWPFRun run = firstPara.createRun();
                  run.setText("\n(本文件由系统自动生成)");
                  run.setItalic(true);
                  run.setColor("808080");
              }
              
              // 在文档末尾添加新内容
              XWPFParagraph newPara = document.createParagraph();
              newPara.setAlignment(ParagraphAlignment.RIGHT);
              XWPFRun newRun = newPara.createRun();
              newRun.setText("生成时间: " + LocalDate.now());
              newRun.addBreak(BreakType.PAGE); // 分页符
              
              // 保存修改后的文档
              try (FileOutputStream fos = new FileOutputStream(outputPath)) {
                  document.write(fos);
              }
          }
      }

      六、高级功能

      1. 页眉页脚设置

      // 创建页眉
      XWPFHeader header = document.createHeader(HeaderFooterType.DEFAULT);
      XWPFParagraph headerPara = header.createParagraph();
      headerPara.setAlignment(ParagraphAlignment.RIGHT);
      XWPFRun headerRun = headerPara.createRun();
      headerRun.setText("公司机密");
      headerRun.setColor("FF0000");
      
      // 创建页脚
      XWPFFooter footer = document.createFooter(HeaderFooterType.DEFAULT);
      XWPFParagraph footerPara = footer.createParagraph();
      footerPara.setAlignment(ParagraphAlignment.CENTER);
      XWPFRun footerRun = footerPara.createRun();
      footerRun.setText("页码: ");
      footerRun.getCTR().addNewFldSimple().setInstr("PAGE \\* MERGEFORMAT");
      

      2. 目录生成

      // 创建目录段落
      XWPFParagraph tocPara = document.createParagraph();
      tocPara.setStyle("TOCHeading");
      
      XWPFRun tocRun = tocPara.createRun();
      tocRun.setText("目录");
      tocRun.setBold(true);
      tocRun.setFontSize(16);
      tocRun.addBreak();
      
      // 添加目录字段
      tocRun = tocPara.createRun();
      tocRun.getCTR().addNewFldSimple().setInstr("TOC \\o \"1-3\" \\h \\z \\u");
      

      3. 批注(注释)添加

      // 在第一个段落添加批注
      XWPFParagraph firstPara = document.getParagraphs().get(0);
      String commentText = "这是系统自动添加的批注";
      String commentAuthor = "AutoSystem";
      CTComment ctComment = document.getDocument().getBody().addNewComment();
      ctComment.setAuthor(commentAuthor);
      ctComment.setDate(new GregorianCalendar());
      ctComment.addNewP().addNewR().addNewT().setStringValue(commentText);
      
      // 将段落与批注关联
      CTMarkupRange range = firstPara.getCTP().addNewCommentRangeStart();
      range.setId(ctComment.getId());
      firstPara.getCTP().addNewCommentRangeEnd().setId(ctComment.getId());
      firstPara.getCTP().addNewR().addNewCommentReference().setId(ctComment.getId());
      

      七、性能优化与最佳实践

      1. 大文件处理优化

      对于大文档,建议使用事件模型(XWPFEvenwww.devze.comtAPI)而非DOM模型:

      import org.apache.poi.xwpf.eventusermodel.*;
      
      public class LargeDocumentReader {
          public static void main(String[] args) throws Exception {
              OPCPackage pkg = OPCPackage.open("large.docx");
              XWPFEventBasedParser parser = new XWPFEventBasedParser();
              parser.parse(pkg, new XWPFVisitor() {
                  @Override
                  public void visitParagraph(XWPFParagraph paragraph) {
                      System.out.println("段落: " + paragraph.getText());
                  }
       js           
                  @Override
                  public void visitTable(XWPFTable table) {
                      System.out.println("发现表格");
                  }
              });
              pkg.close();
          }
      }
      

      2. 内存管理

      及时关闭文档对象和流

      对于批量处理,考虑复用XWPFDocument对象

      使用try-with-resources确保资源释放

      3. 样式重用

      // 创建并重用样式
      CTSectPr sectPr = document.getDocument().getBody().addNewSectPr();
      CTPageSz pageSz = sectPr.addNewPgSz();
      pageSz.setW(BigInteger.valueOf(12240)); // A4宽度
      pageSz.setH(BigInteger.valueOf(15840)); // A4高度
      
      // 创建段落样式
      CTStyle ctStyle = CTStyle.Factory.newInstance();
      ctStyle.setStyleId("MyStyle");
      CTPPr pPr = ctStyle.addNewPPr();
      pPr.addNewSpacing().setAfter(BigInteger.valueOf(200)); // 段后间距
      document.getStyle().addStyle(ctStyle);
      
      ​​​​​​​// 应用样式
      XWPFParagraph para = document.createParagraph();
      para.setStyle("MyStyle");

      八、常见问题与解决方案

      1. 中文乱码问题

      确保使用支持中文的字体:

      run.setFontFamily("宋体");
      

      或者在文档级别设置默认字体:

      document.getStyles().setDefaultFonts("宋体", null);
      

      2. 格式不兼容问题

      尽量使用.docx格式而非.doc格式

      避免使用太新的Office特性

      在生成文档后进行兼容性测试

      3. 性能问题

      对于大文档,分批次处理内容

      避免频繁创建/销毁XWPFRun对象

      考虑缓存常用样式

      九、总结

      Apache POI提供了强大而灵活的API来操作Word文档,从简单的文本生成到复杂的格式设置、表格处理和图片插入都能胜任。通过本文的介绍,您应该已经掌握了:

      • 基本的文档创建与保存
      • 文本格式设置与段落控制
      • 表格的创建与样式设置
      • 图片插入方法
      • 现有文档的读取与修改
      • 高级功能如页眉页脚、目录生成
      • 性能优化技巧

      在实际项目中,建议根据具体需求选择合适的API,并注意资源管理和性能优化。对于更复杂的需求,可以结合模板引擎或考虑商业解决方案。

      到此这篇关于从入门到实战详解如何使用Apache POI操作Word文档的文章就介绍到这了,更多相关Apache POI操作Word内容请搜索编程客栈(www.devze.com)以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程客栈(www.devze.com)!

      0

      上一篇:

      下一篇:

      精彩评论

      暂无评论...
      验证码 换一张
      取 消

      最新开发

      开发排行榜