package doc;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.poi.ooxml.POIXMLDocument;
import org.apache.poi.xwpf.usermodel.XWPFComment;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
public class AnnoDemo {
/** 批注所引用正文装配Map完毕标识 */
private static final String COMMENT_REF_FILLED_OK = "OK";
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");
/** 批注最大下标 */
private String maxCommentIndex;
/* * @param filePath Word文件路径 */
public AnnoDemo(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());
}
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();
AnnoDemo wh = new AnnoDemo("C:\\Users\\iuit\\Desktop\\111.docx");
XWPFComment[] comments = wh.getComments();
System.out.println("备注个数="+comments.length);
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("批注内容:").append(comment.getText())
.append(", ").append("批注引用正文:")
.append(commenRefMap.get(comment.getId()));
value.append("\n");
}
System.out.println(value);
}
}