为了精准的获取目录的页码、内容、以及前置标题列,我才去的是逐段读取的方式,但由于word中每个表格的单元格都占用一个段落,因此如果真的逐段扫描速度会很慢。因此可以在读取之前把表格给干掉。
- 获取所有表格
//所有表格
Dispatch tables = Dispatch.get(doc, "Tables").toDispatch();
//获取表格总数
int tableCount = Dispatch.get(tables, "Count").getInt();
-
删除所有表格
在这里我做的是打开文档和读取大纲操作,不会对其进行保存·操作,所以结束后对文档内容本身是不会有影响。
for (int i = ; i < tableCount ; i++) {
table = Dispatch.call(tables, "Item", new Variant()).toDispatch();
Dispatch.call(table, "Delete");
}
完整代码如下
- 在这里要解释一下为什么要从后往前读。
- 因为我这里需求是需要读取文档目录并有相应的目录结构(层次关系,比如说1 下面有1.1 和1.2 ,1.1下面有1.1.1),并转换成json字符串发送到移动端,移动端通过json字符串展示目录,并能通过页码索引到对应的位置。
- 所以这里我就没改动读取方向了,有问题可以多多交流,JACOB坑太多了,可以多交流交流。
public class ReadWordOrWPSBookMarks {
/**
* 读取word/wps文档的大纲
* @param filename 要打开的文档的目录(带文件名)
* @param strChoose 打开方式 Microsoft Word: 2 WPS: 3
*/
public static void readBookMarksByWordOrWps(String filename, String strChoose) {
ActiveXComponent app = null;
Dispatch doc = null;
try {
//microsoft Office 方式
if ( "2".equals(strChoose) ) {
app = new ActiveXComponent("Word.Application");
}
//WPS 方式
if ( "3".equals(strChoose) ) {
app = new ActiveXComponent("KWPS.Application");
}
app.setProperty("Visible", new Variant(false));
Dispatch docs = app.getProperty("Documents").toDispatch();
doc = Dispatch.call(docs, "Open", filename).toDispatch();
//所有表格
Dispatch tables = Dispatch.get(doc, "Tables").toDispatch();
//获取表格总数
int tableCount = Dispatch.get(tables, "Count").getInt();
System.out.println("表格数" + tableCount);
Dispatch table = null;
//删除所有表格(删除第一个表格后,第二个表格会变成第一表格)
for (int i = ; i < tableCount ; i++) {
table = Dispatch.call(tables, "Item", new Variant()).toDispatch();
Dispatch.call(table, "Delete");
}
// 获取大纲列表
Dispatch paragraphs = Dispatch.get(doc, "Paragraphs").toDispatch();
int count = Dispatch.get(paragraphs, "Count").getInt();//大纲数量
//当前大纲等级层次
int tempLevel = ;
//从后往前获取大纲
for (int i = count - ; i >= ; i--) {
//当前大纲项
Dispatch paragraph = Dispatch.call(paragraphs, "Item", new Variant(i+)).toDispatch();
//大纲等级
int level = Dispatch.get(paragraph, "OutlineLevel").getInt();
Dispatch paragraphRange = Dispatch.get(paragraph, "Range").toDispatch();
//一般目录不会超过4级,4级往后是内容,可以跳过
if ( level <= ) {
if ( tempLevel == ) {
tempLevel = level ;
}
//标题编号
Dispatch listFormat = Dispatch.get(paragraphRange, "ListFormat").toDispatch();
String listString = "";
try {
listString = Dispatch.get(listFormat, "ListString").toString();
} catch (Exception e) {
System.out.println("没有ListForat属性的标题:" + Dispatch.get(paragraphRange, "Text").toString().replaceAll("\\\r|\\\f", ""));
}
//标题
String text = Dispatch.get(paragraphRange, "Text").toString().replaceAll("\\\r|\\\f", "") ;
//可能会存在一些为空的隐藏的大纲,text是为空的
if (text == null || ("").equals(text)) {
continue;
}
text = listString + text;
//索引的页码
int page = Dispatch.call(paragraphRange, "information", ).getInt() ;
System.out.println("text:"+text + " page:"+page + " level:"+level);
}
}
} catch (Exception e) {
System.out.println(" 大纲获取失败" , e);
} finally {
try {
Dispatch.call(doc, "Close", false);
if (app != null){
app.invoke("Quit", new Variant[] {});
app = null;
}
} catch (Exception e2) {
System.out.println("关闭ActiveXComponent异常");
}
}
}