使用Apache POI 3.17读取并编辑Word文档中的图表
问题描述
需要使用Apache POI读取并编辑Microsoft Word文档中的图表。已知Apache POI 4及更高版本提供了XWPFChart类用于处理Word中的图表,但在POI 3.17版本中没有对应的图表操作类。目前已编写了部分代码,请求帮助编写获取图表Workbook对象的代码。
现有代码如下:
try (XWPFDocument doc = new XWPFDocument(Files.newInputStream(Paths.get(fileName)))) { // output the same as 8.1 List<XWPFParagraph> list = doc.getParagraphs(); for (XWPFParagraph paragraph : list) { // System.out.println(paragraph.getText()); } for (POIXMLDocumentPart part : doc.getRelations()) { if (!StringUtils.equalsIgnoreCase(part.getPackagePart().getContentTypeDetails().getSubType(),"vnd.openxmlformats-officedocument.drawingml.chart+xml")) { System.out.println("Name ->" + part.toString() + ", Class -> " + part.getClass() + ", Parent Part ->" + part.getPackagePart().getContentTypeDetails().getSubType()); } continue; } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); }
解决方案(POI 3.17版本)
在POI 3.17中没有封装好的XWPFChart类,需手动解析Word的OOXML结构来获取图表关联的Workbook对象,核心步骤如下:
- 遍历文档部件,筛选出图表类型的部件(contentType子类型为
vnd.openxmlformats-officedocument.drawingml.chart+xml); - 针对每个图表部件,查找其关联的嵌入式Excel工作簿部件;
- 从该部件的输入流中构建
XSSFWorkbook对象。
修改后的完整代码:
import org.apache.poi.openxml4j.opc.PackagePart; import org.apache.poi.openxml4j.opc.PackageRelationship; import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.apache.poi.xwpf.usermodel.XWPFDocument; import org.apache.poi.xwpf.usermodel.XWPFParagraph; import org.apache.commons.lang3.StringUtils; import java.io.IOException; import java.io.InputStream; import java.nio.file.Files; import java.nio.file.Paths; import java.util.List; public class WordChartReader { public static void main(String[] args) { String fileName = "your-word-file.docx"; // 替换为你的Word文件路径 try (XWPFDocument doc = new XWPFDocument(Files.newInputStream(Paths.get(fileName)))) { // 遍历文档段落(保留原代码逻辑) List<XWPFParagraph> list = doc.getParagraphs(); for (XWPFParagraph paragraph : list) { // System.out.println(paragraph.getText()); } // 遍历所有部件,处理图表 for (POIXMLDocumentPart part : doc.getRelations()) { PackagePart packagePart = part.getPackagePart(); String subType = packagePart.getContentTypeDetails().getSubType(); // 筛选图表类型部件 if (StringUtils.equalsIgnoreCase(subType, "vnd.openxmlformats-officedocument.drawingml.chart+xml")) { // 查找关联的嵌入式Excel工作簿 List<PackageRelationship> relationships = packagePart.getRelationshipsByType( "http://schemas.openxmlformats.org/officeDocument/2006/relationships/package" ); for (PackageRelationship rel : relationships) { PackagePart embeddedPart = packagePart.getRelatedPart(rel); // 判断是否为Excel工作簿 if (embeddedPart.getContentType().equals("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")) { try (InputStream is = embeddedPart.getInputStream()) { // 构建Workbook对象 Workbook workbook = new XSSFWorkbook(is); // 此处可对Workbook进行读取、编辑操作 System.out.println("成功获取图表关联Workbook,工作表数量:" + workbook.getNumberOfSheets()); // 示例:读取第一个工作表数据 // XSSFSheet sheet = (XSSFSheet) workbook.getSheetAt(0); // 后续业务逻辑... } } } } } } catch (IOException e) { e.printStackTrace(); } } }
关键说明
- Word中的图表数据实际存储在嵌入式Excel工作簿中,而非图表部件本身,因此需要通过图表部件的关系找到对应的Excel部件;
- 使用
http://schemas.openxmlformats.org/officeDocument/2006/relationships/package作为关系类型,这是OOXML中嵌入式部件的标准关联类型; - 采用try-with-resources语法确保输入流和Workbook资源被正确释放,避免内存泄漏。
内容的提问来源于stack exchange,提问作者Nitin Rathod
相关产品推荐
相关产品推荐

