從入門到實戰(zhàn)詳解如何使用Apache?POI操作Word文檔
Apache POI是Java生態(tài)中最流行的Microsoft Office文檔操作庫之一,它為Word文檔(包括傳統(tǒng)的.doc格式和現(xiàn)代的.docx格式)提供了全面的API支持。本文將詳細(xì)介紹如何使用Apache POI創(chuàng)建、讀取和修改Word文檔。
一、Apache POI簡介與環(huán)境準(zhǔn)備
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:段落中的文本運(yùn)行(具有相同格式的文本段)
XWPFTable:表格
XWPFPicture:圖片
二、創(chuàng)建Word文檔
1. 創(chuàng)建簡單文檔
import org.apache.poi.xwpf.usermodel.*;
import java.io.FileOutputStream;
import java.io.IOException;
public class SimpleDocumentCreator {
public static void main(String[] args) throws IOException {
// 1. 創(chuàng)建空文檔
XWPFDocument document = new XWPFDocument();
// 2. 創(chuàng)建段落
XWPFParagraph title = document.createParagraph();
title.setAlignment(ParagraphAlignment.CENTER);
// 3. 創(chuàng)建文本運(yùn)行并設(shè)置樣式
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); // 首行縮進(jìn)
XWPFRun bodyRun = body.createRun();
bodyRun.setText("這是使用Apache POI創(chuàng)建的Word文檔。");
bodyRun.addBreak(); // 換行
bodyRun.setText("POI支持豐富的文本格式設(shè)置。");
// 5. 保存文檔
try (FileOutputStream out = new FileOutputStream("SimpleDocument.docx")) {
document.write(out);
}
document.close();
System.out.println("文檔創(chuàng)建成功!");
}
}
2. 添加復(fù)雜格式
// 創(chuàng)建帶格式的段落
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);
三、操作表格
1. 創(chuàng)建表格
// 創(chuàng)建3行4列的表格
XWPFTable table = document.createTable(3, 4);
// 設(shè)置表格寬度
table.setWidth("100%");
// 填充表頭
XWPFTableRow headerRow = table.getRow(0);
headerRow.getCell(0).setText("序號");
headerRow.getCell(1).setText("姓名");
headerRow.getCell(2).setText("年齡");
headerRow.getCell(3).setText("部門");
// 填充數(shù)據(jù)
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 ? "技術(shù)部" : "市場部");
}
// 合并單元格
table.getRow(2).getCell(3).setText("備注:所有部門");
table.addNewColSpan(2, 3, 2); // 合并第3行的第3-4列
2. 表格樣式設(shè)置
// 設(shè)置表格邊框
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);
// 設(shè)置表頭背景色
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)); // 高度
}
// 從字節(jié)數(shù)組插入圖片
byte[] imageData = getImageData(); // 獲取圖片字節(jié)數(shù)組的方法
XWPFRun imageRun = document.createParagraph().createRun();
imageRun.addPicture(new ByteArrayInputStream(imageData),
Document.PICTURE_TYPE_JPEG,
"photo.jpg",
Units.toEMU(150),
Units.toEMU(150));
五、讀取和修改現(xiàn)有文檔
1. 讀取文檔內(nèi)容
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. 修改現(xiàn)有文檔
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(本文件由系統(tǒng)自動生成)");
run.setItalic(true);
run.setColor("808080");
}
// 在文檔末尾添加新內(nèi)容
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. 頁眉頁腳設(shè)置
// 創(chuàng)建頁眉
XWPFHeader header = document.createHeader(HeaderFooterType.DEFAULT);
XWPFParagraph headerPara = header.createParagraph();
headerPara.setAlignment(ParagraphAlignment.RIGHT);
XWPFRun headerRun = headerPara.createRun();
headerRun.setText("公司機(jī)密");
headerRun.setColor("FF0000");
// 創(chuàng)建頁腳
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. 目錄生成
// 創(chuàng)建目錄段落
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 = "這是系統(tǒng)自動添加的批注"; String commentAuthor = "AutoSystem"; CTComment ctComment = document.getDocument().getBody().addNewComment(); ctComment.setAuthor(commentAuthor); ctComment.setDate(new GregorianCalendar()); ctComment.addNewP().addNewR().addNewT().setStringValue(commentText); // 將段落與批注關(guān)聯(lián) CTMarkupRange range = firstPara.getCTP().addNewCommentRangeStart(); range.setId(ctComment.getId()); firstPara.getCTP().addNewCommentRangeEnd().setId(ctComment.getId()); firstPara.getCTP().addNewR().addNewCommentReference().setId(ctComment.getId());
七、性能優(yōu)化與最佳實踐
1. 大文件處理優(yōu)化
對于大文檔,建議使用事件模型(XWPFEventAPI)而非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());
}
@Override
public void visitTable(XWPFTable table) {
System.out.println("發(fā)現(xiàn)表格");
}
});
pkg.close();
}
}
2. 內(nèi)存管理
及時關(guān)閉文檔對象和流
對于批量處理,考慮復(fù)用XWPFDocument對象
使用try-with-resources確保資源釋放
3. 樣式重用
// 創(chuàng)建并重用樣式
CTSectPr sectPr = document.getDocument().getBody().addNewSectPr();
CTPageSz pageSz = sectPr.addNewPgSz();
pageSz.setW(BigInteger.valueOf(12240)); // A4寬度
pageSz.setH(BigInteger.valueOf(15840)); // A4高度
// 創(chuàng)建段落樣式
CTStyle ctStyle = CTStyle.Factory.newInstance();
ctStyle.setStyleId("MyStyle");
CTPPr pPr = ctStyle.addNewPPr();
pPr.addNewSpacing().setAfter(BigInteger.valueOf(200)); // 段后間距
document.getStyle().addStyle(ctStyle);
???????// 應(yīng)用樣式
XWPFParagraph para = document.createParagraph();
para.setStyle("MyStyle");八、常見問題與解決方案
1. 中文亂碼問題
確保使用支持中文的字體:
run.setFontFamily("宋體");
或者在文檔級別設(shè)置默認(rèn)字體:
document.getStyles().setDefaultFonts("宋體", null);
2. 格式不兼容問題
盡量使用.docx格式而非.doc格式
避免使用太新的Office特性
在生成文檔后進(jìn)行兼容性測試
3. 性能問題
對于大文檔,分批次處理內(nèi)容
避免頻繁創(chuàng)建/銷毀XWPFRun對象
考慮緩存常用樣式
九、總結(jié)
Apache POI提供了強(qiáng)大而靈活的API來操作Word文檔,從簡單的文本生成到復(fù)雜的格式設(shè)置、表格處理和圖片插入都能勝任。通過本文的介紹,您應(yīng)該已經(jīng)掌握了:
- 基本的文檔創(chuàng)建與保存
- 文本格式設(shè)置與段落控制
- 表格的創(chuàng)建與樣式設(shè)置
- 圖片插入方法
- 現(xiàn)有文檔的讀取與修改
- 高級功能如頁眉頁腳、目錄生成
- 性能優(yōu)化技巧
在實際項目中,建議根據(jù)具體需求選擇合適的API,并注意資源管理和性能優(yōu)化。對于更復(fù)雜的需求,可以結(jié)合模板引擎或考慮商業(yè)解決方案。
到此這篇關(guān)于從入門到實戰(zhàn)詳解如何使用Apache POI操作Word文檔的文章就介紹到這了,更多相關(guān)Apache POI操作Word內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Spring Boot 實現(xiàn)https ssl免密登錄(X.509 pki登錄)
這篇文章主要介紹了Spring Boot 實現(xiàn)https ssl免密登錄(X.509 pki登錄),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-01-01
Java系統(tǒng)變量參數(shù)獲取設(shè)置System.getProperties()的方法
這篇文章主要介紹了Java系統(tǒng)變量參數(shù)System.getProperties()獲取設(shè)置方法,文末給大家提到了Systm.getenv()與System.getProperties()區(qū)別,需要的朋友可以參考下2022-01-01
解決mybatis分頁插件PageHelper導(dǎo)致自定義攔截器失效
這篇文章主要為大家介紹了解決mybatis分頁插件PageHelper導(dǎo)致自定義攔截器失效方案示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-08-08
Java使用EasyExcel實現(xiàn)對excel文件的讀寫方式
這篇文章主要介紹了Java使用EasyExcel實現(xiàn)對excel文件的讀寫方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-05-05
springboot增加注解緩存@Cacheable的實現(xiàn)
這篇文章主要介紹了springboot增加注解緩存@Cacheable的實現(xiàn),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-12-12
redisson.tryLock()參數(shù)的使用及理解
這篇文章主要介紹了redisson.tryLock()參數(shù)的使用,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-04-04
Spring cloud alibaba之Ribbon負(fù)載均衡實現(xiàn)方案
Spring cloud Ribbon是基于Netflix Ribbon實現(xiàn)的一套客戶端的負(fù)載均衡工具,Ribbon客戶端提供一系列完善的配置,如超時、重試等,Ribbon也可以實現(xiàn)自己的負(fù)載均衡算法,感興趣的朋友跟隨小編一起看看吧2021-07-07
Mybatis Mapper XML文件-插入,更新,刪除詳解(insert, updat
這篇文章主要介紹了MyBatis的Mapper XML文件中用于插入、更新和刪除數(shù)據(jù)的語句,包括這些語句的屬性和子元素的使用方法2025-02-02
mybatis配置mapper-locations位置的三種方式小結(jié)
這篇文章主要給大家介紹了關(guān)于mybatis配置mapper-locations位置的三種方式,Mybatis-Plus的初衷是為了簡化開發(fā),而不建議開發(fā)者自己寫SQL語句的,但是有時客戶需求比較復(fù)雜,需要的朋友可以參考下2023-08-08

