`
53873039oycg
  • 浏览: 841706 次
  • 性别: Icon_minigender_1
社区版块
存档分类
最新评论

[整理]poi读取word 2007批注信息

    博客分类:
  • poi
 
阅读更多

       本文非原创,只是整理了下代码,原代码出自:http://blog.chiefleo.me/archives/429.原文如下:

       

      普通的读取批注信息方法:

     

public void readWordDocxComments(String fileName) {
		XWPFDocument document = null;
		XWPFComment[] comments = null;
		try {
			document = new XWPFDocument(POIXMLDocument.openPackage(fileName));
			comments = document.getComments();
			for (int i = 0; i < comments.length; i++) {
				System.out.println("Id= " + comments[i].getId());
				System.out.println("Text= " + comments[i].getText());
				System.out.println("Author= " + comments[i].getAuthor());
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

    不能获取批注对应的正文信息,修改后的代码如下:

   

import java.io.File;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.apache.poi.POIXMLDocument;
import org.apache.poi.POIXMLDocumentPart;
import org.apache.poi.xwpf.usermodel.XWPFComment;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFRelation;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTComment;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CommentsDocument;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CommentsDocument.Factory;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

public class POI_读取批注_S4_Test {
	private File file;
	/** Word document */
	private XWPFDocument docx;
	/** 批注内容数组 */
	private XWPFComment[] comments;//
	/** 批注引用正文map,结构-<批注Id,正文text> */
	private Map<String, String> commentRefs;// /** 日期格式化类型 */
	private final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
	/** 批注所引用正文装配Map完毕标识 */
	private static final String COMMENT_REF_FILLED_OK = "OK";
	/** 批注最大下标 */
	private String maxCommentIndex;

	/*
	 * @param filePath Word文件路径
	 */
	public POI_读取批注_S4_Test(String filePath) throws Exception {
		file = new File(filePath);
		initAttributes();
	} 
	
	/*
	 * 初始化成员变量
	 * @throws Exception Word缺陷导入异常
	 */
	private void initAttributes() throws Exception {
		try {
			docx = new XWPFDocument(POIXMLDocument.openPackage(file
					.getCanonicalPath()));
			comments = docx.getComments();
			maxCommentIndex = String.valueOf(comments.length - 1);
			commentRefs = new HashMap<String, String>();
			fillCommentRef(docx.getDocument().getDomNode(),
					new StringBuilder(), new StringBuilder(),
					new StringBuilder(), commentRefs);
		} catch (Exception e) {
			throw new Exception(new StringBuilder().append("Word文件格式错误")
					.append("-").append(e.getMessage()).toString(), e);
		}
	}

	/*
	 * 获取批注内容
	 */
	public XWPFComment[] getComments() {
		return comments;
	}

	public Map<String, String> getCommentRefs() {
		return commentRefs;
	}

	/*
	 * 获取日期格式化类型
	 */
	public SimpleDateFormat getSdf() {
		return sdf;
	}

	/* 获取批注日期List */
	public List<Date> getSubmitDateList() {
		Map<String, Date> dateMap = new HashMap<String, Date>();
		List<Date> dateList = new ArrayList<Date>();
		try {
			Iterator<POIXMLDocumentPart> iter = docx.getRelations().iterator();
			do {
				if (!iter.hasNext())
					break;
				POIXMLDocumentPart p = (POIXMLDocumentPart) iter.next();
				String relation = p.getPackageRelationship()
						.getRelationshipType();
				if (relation.equals(XWPFRelation.COMMENT.getRelation())) {
					CommentsDocument cmntdoc;
					cmntdoc = Factory
							.parse(p.getPackagePart().getInputStream());
					List<CTComment> commentList = cmntdoc.getComments()
							.getCommentList();
					int len = commentList.size();
					int j = 0;
					while (j < len) {
						CTComment ctcomment = commentList.get(j);
						dateMap.put(ctcomment.getId().toString(), ctcomment
								.getDate().getTime());
						j++;
					}
				}
			} while (true);
		} catch (Exception e) {
		}
		if (dateMap != null) {
			for (XWPFComment comment : comments) {
				dateList.add(dateMap.get(comment.getId()));
			}
		}
		return dateList;
	}

	/*
	 * 获取批注作者List
	 */
	public List<String> getSubmitterList() {
		List<String> list = new ArrayList<String>();
		for (XWPFComment comment : comments) {
			list.add(comment.getAuthor().trim());
		}
		return list;
	}
	/*
	 * 组装批注引用文本Map,Map结构-<commentId,text>
	 * @param node WordProcessingML node
	 * @param id 批注ID
	 * @param value 批注引用正文文本
	 * @param convertOK 正文组装完毕标识 ,组装完毕 = "OK"
	 * @param map 要填充的目标Map
	 */
	private void fillCommentRef(Node node, StringBuilder id,
			StringBuilder value, StringBuilder convertOK,
			Map<String, String> map) throws Exception {
		// fillCommentRef方法要求所有参数不能为null,如果为null,抛出异常
		if (!insureNotNull(node, id, value, convertOK, map)) {
			throw new IllegalArgumentException(new StringBuilder()
					.append(this.getClass().getName())
					.append("fillCommentRef(").append(node).append(",")
					.append(id).append(",").append(value).append(",")
					.append(convertOK).append(",").append(map).append(")")
					.toString());
		}
		/*
		 * docx文件批注所引用的正文保存在document.xml中,可以通过重命名xx.docx为xx.zip来查看
		 * 其中如果某段正文文本内容有批注,那么会在document.xml这样保存 <w:commentRangeStart w:id="0" />
		 * <w:t>正文文本</w:t> </w:r> <w:commentRangeEnd w:id="0" />
		 * 如果被批注的是在图片上加批注,那么会在document
		 * .xml中这样保存(仅限真正docx文件,如果是doc文件另存为docx文件,<wp:docPr节点中是没有属性的)
		 * <w:commentRangeStart w:id="1" /> <wp:docPr id="1" name="xxx"
		 * descr="yyy.png" /> <w:commentRangeEnd w:id="1" /> *
		 * 1)id初始值为空,如果解析到节点w:commentRangeStart,就代表是有批注的部分,需要把参数id设为节点的id属性值
		 * 2)顺次解析下面节点
		 * ,如果此时的id不为空,就代表进入批注引用部分,w:t是文本内容,直接append;wp:docPr是图片内容,用"[xxx]"
		 * 来区分是图片,然后append.
		 * 3)如果解析到节点w:commentRangeEnd,就代表一个批注引用完毕,这时需要向Map中put(id,value)值;
		 * 判断当前的批注Id是不是最大
		 * ,如果为最大批注Id,convertOK置为"OK",用此标识来说明批注引用提取完毕,退出节点for循环?例如一个很大的Word文件
		 * ,只在第2页做了一个批注,前面的做法会很有用;
		 * 同时还要做好一条批注引用解析完毕的收尾工作:id清空,代表下面节点又是无批注的部分;value清空,待下次新的批注append.
		 */
		if ("w:t".equals(node.getNodeName()) && id.length() > 0) {
			value.append(node.getFirstChild().getNodeValue());
		} else if ("wp:docPr".equals(node.getNodeName()) && id.length() > 0) {
			value.append("[").append(getAttribute(node, "name")).append("]");
		} else if ("w:commentRangeStart".equals(node.getNodeName())) {
			id.setLength(0);
			id.append(getAttribute(node, "w:id"));
			value.setLength(0);
		} else if ("w:commentRangeEnd".equals(node.getNodeName())
				&& id.length() > 0) {
			if (id.toString().equals(getAttribute(node, "w:id"))) {
				map.put(id.toString(), value.toString());
				if (id.toString().equals(maxCommentIndex)) {
					convertOK.setLength(0);
					convertOK.append(COMMENT_REF_FILLED_OK);
					id.setLength(0);
					value.setLength(0);
				}
			}
		}
		if (node.hasChildNodes()) {
			NodeList temp = node.getChildNodes();
			for (int i = 0; i < temp.getLength(); i++) {
				if (convertOK.toString().endsWith(COMMENT_REF_FILLED_OK)) {
					break;
				}
				fillCommentRef(temp.item(i), id, value, convertOK, map);
			}
		}
	}

	/***
	 * @param node
	 *            当前的Node
	 * @param attName
	 *            要获取的属性名
	 * @return 属性值,没有该属性时返回null
	 */
	private static String getAttribute(Node node, String attName) {
		return (node.hasAttributes() && node.getAttributes().getNamedItem(
				attName) != null) ? node.getAttributes().getNamedItem(attName)
				.getNodeValue() : null;
	}

	/*
	 * 确保此方法的所有参数均不为空
	 * @param objects 对象参数
	 * @return 所有参数均不为空返回true 否则为false
	 */
	private boolean insureNotNull(Object... objects) {
		for (Object object : objects) {
			if (object == null) {
				return false;
			}
		}
		return true;
	}

	public static void main(String[] args) throws Exception {
		StringBuffer value = new StringBuffer();
		POI_读取批注_S4_Test wh = new POI_读取批注_S4_Test(
				"f:/saveFile/temp/sys_comment_07.docx");
		XWPFComment[] comments = wh.getComments();
		Map<String, String> commenRefMap = wh.getCommentRefs();
		List<Date> l = wh.getSubmitDateList();
		SimpleDateFormat sdf = wh.getSdf();
		XWPFComment comment;
		for (int i = 0; i < comments.length; i++) {
			comment = comments[i];
			value.append("批注Id:").append(comment.getId()).append(", ")
					.append("批注作者:").append(comment.getAuthor()).append(", ")
					.append("批注日期:").append(sdf.format(l.get(i))).append(", ")
					.append("批注内容:").append(comment.getText()).append(", ")
					.append("批注引用正文:")
					.append(commenRefMap.get(comment.getId()));
			value.append("\n");
		}
		System.out.println(value);
	}
}

   结果为:

  

   

     全文完。

     

  • 大小: 172.1 KB
  • 大小: 85.6 KB
  • 大小: 88.5 KB
0
0
分享到:
评论
1 楼 追追追太阳 2016-02-21  
我复制了你的代码,运行时报错:java.lang.NoClassDefFoundError: org/openxmlformats/schemas/wordprocessingml/x2006/main/impl/CTCommentsImpl$1CommentList
at org.openxmlformats.schemas.wordprocessingml.x2006.main.impl.CTCommentsImpl.getCommentList(Unknown Source)
at com.makeWord.POI_读取批注_S4_Test.getSubmitDateList(POI_读取批注_S4_Test.java:99)
at com.makeWord.POI_读取批注_S4_Test.main(POI_读取批注_S4_Test.java:232)
请教一下你用的包是什么版本的呢,这个错误是不是因为我的包不全呢?

相关推荐

    java poi读取word

    首先,让我们了解如何通过Java POI读取Word文档。在Java中,我们需要导入`org.apache.poi.xwpf.usermodel`包,因为这个包包含了处理`.docx`文件所需的类。`.docx`是Word 2007及更高版本使用的XML格式。以下是一个...

    java读取word2003

    在Java编程环境中,读取Word 2003文档是一项常见的任务,这通常涉及到处理`.doc`文件格式。为了实现这个功能,开发者可以利用各种库,如Apache POI或者JODConverter。Apache POI是一个流行的开源项目,它提供了对...

    java 使用POI合并两个word文档.docx

    Java 使用 POI 合并两个 Word 文档 Java 是一种流行的编程语言,POI(Poor Obfuscation Implementation)是一个流行的 Java 库,用于操作 Microsoft Office 文件,包括 Word 文档。合并两个 Word 文档是指将两个...

    获取word文件中的标题、序号、批注等工具类

    使用aspose.words,获取word文件中的标题,批注,批注所在标题,标题序号,在书签处插入图片,在指定文字处插入图片等

    java web在线预览pdf、word、excel

    为了实现文档预览,我们需要创建一个Controller,该Controller接收前端请求,读取服务器上的PDF、Word或Excel文件,然后将文件内容转换为适合在浏览器中展示的格式。 对于PDF文件,在Java Web环境中,可以使用...

    POI所有.rar

    5. **批注和注释**:POI提供了处理Excel批注和Word注释的功能,可以读取、添加和修改这些元数据。 6. **事件模型**:为处理大型文件,POI提供了事件模型(SXSSF),这是一种基于内存优化的低级别API,可以避免加载...

    poi.jar(poi)

    - 兼容性:除了基本的读写功能,POI还支持解析和生成复杂的公式、图表、超链接、批注等。 - 错误处理:提供完善的异常处理机制,帮助开发者定位和解决问题。 8. **示例代码**: - 创建一个新的Excel文件并写入...

    Java poi操作表格

    Java POI是一个强大的库,由Apache软件基金会开发,专门用于处理Microsoft Office格式的文件,特别是Excel、Word和PowerPoint文档。在Java世界中,如果你需要读取、创建或修改Excel电子表格,Java POI就是不可或缺的...

    Java 获取Word中的所有插入和删除修订.doc

    Java 获取 Word 中的所有插入和删除修订 在 Word 文档中启用跟踪更改功能后,会记录文档中的所有编辑行为,例如插入、删除、替换和格式更改。这篇文章将介绍如何使用 Java 获取 Word 文档中的所有插入和删除修订。 ...

    ExportComments.7z

    "标签"中的"java"表明了编程语言,"导出word批注"指出了主要功能,而"poi"则明确表示了使用的技术栈。Apache POI库提供了一系列接口,比如HWPF(用于处理老版本的DOC文件)和XWPF(用于处理新版本的DOCX文件),来...

    java在线预览,POI对应jar包大全

    例如,读取Excel文件可以用`XSSFWorkbook`,读取Word文件用`XWPFDocument`,读取PowerPoint文件用`XMLSlideShow`。 3. **转换为HTML**:为了在线预览,需要将文档内容转换为HTML格式。这通常涉及到解析Office文档的...

    word批量转pdf小工具.zip

    值得注意的是,为了确保转换的纯净性,用户被建议在转换前删除Word文档中的批注。 这个小工具的实现可能基于对Microsoft Office接口的调用,或者使用了专门的文档转换库,例如Apache POI for .NET或其他第三方库。...

    操作 Office Open XML 格式文档

    3. **Java的Apache POI**:支持处理Word、Excel和PowerPoint的OOXML文件。 **应用场景** - 自动化文档生成:编程生成报告、合同或其他格式化的文本。 - 数据提取:从大量Excel文件中提取数据进行分析。 - 文档转换...

    PageOffice 基础教程.pdf

    它还详细解释了PageOffice在OA系统中实现文档在线编辑及流转痕迹保留、键盘批注、手写批注等高级功能的方法。这些功能的实现依赖于PageOffice如何与数据库交互,并且教程解释了SaveDataPage和SaveFilePage这两个关键...

    NPOI使用手册,关于NPOI的操作

    随着项目的发展,NPOI可能会考虑自研对Word文档的支持,以弥补Java POI中HWPF的不足。 总之,NPOI是.NET开发者处理Excel文件的强大工具,提供了丰富的API来创建、读取和修改Excel内容,同时支持各种复杂的格式设置...

    NPOI examples

    8. **批注和超链接**:NPOI允许你在单元格中添加批注,或者为单元格设置超链接,以增强信息的交互性。 9. **性能优化**:NPOI采用流式处理,对于大数据量的文件,可以减少内存占用,提高处理效率。 10. **兼容性**...

    毕业设计论文-通用作业批改系统.zip

    5. 文件处理:使用Apache POI或JavaFX的文件处理API,处理上传的Word文档或其他格式的作业。 三、系统架构 1. 用户模块:包含教师和学生的账号管理,登录验证,权限控制等功能。 2. 作业管理模块:教师可以发布作业...

    NPOI使用手册

    **NPOI** 是一个基于 Apache POI 的 .NET 库,用于在没有安装 Microsoft Office 的情况下读写 Office 文件。它最初是为了满足 .NET 开发者在 C# 和其他 .NET 语言中处理 Excel 文件的需求而开发的。NPOI 目前支持 ...

Global site tag (gtag.js) - Google Analytics