描述:
我做了一个com自动化客户程序,用来操作word文档,读出我要内容(不考虑图片)。
我要实现可以按章,节来读出数据。(请教思路)
目前我的代码只能读出word文档中的段落内容。具体代码如下。。。
void readWord()
{
//初始化COM
if (CoInitialize(NULL)!=0)
{
AfxMessageBox("初始化COM支持库失败!");
exit(1);
}
// word object
_Application wordApp;
_Document doc;
Documents docs;
Styles styles;
Style style;
Paragraphs pgraphs;
Paragraph pgraph;
Range range;
Range range1;
Tables tables;
Table table;
Rows rows;
Row row;
Cells cells;
Cell cell;
COleVariant vFileName("c:\\a3.doc");
COleVariant varstrNull("");
COleVariant vLong((long)DISP_E_PARAMNOTFOUND,VT_ERROR);
COleVariant vTrue((short)TRUE);
COleVariant vFalse((short)FALSE);
CFile myfile;
CString strBuf;
long i;
//创建一个新的word程序
if(!wordApp.CreateDispatch("Word.Application",NULL))
{
AfxMessageBox("创建ms_word服务失败");
exit(1);
}
docs.AttachDispatch(wordApp.GetDocuments());
doc = docs.Open(vFileName,vFalse,vFalse,vFalse,
varstrNull,varstrNull,vFalse,varstrNull,
varstrNull,vFalse,vFalse,vFalse);
pgraphs.AttachDispatch(doc.GetParagraphs());
for(i=1; i<=pgraphs.GetCount(); i++)
{
pgraph = pgraphs.Item(i);
(Q1) // afxDump<<pgraph.GetStyle().bVal;
range = pgraph.GetRange();
if(Tables(range.GetTables()).GetCount() > 0)
{
afxDump<<"cell content: ";
afxDump<<range.GetText();
afxDump<<"\n";
}
else
{
afxDump<<"content: ";
afxDump<<range.GetText();
afxDump<<"\n";
}
}
cell.ReleaseDispatch();
cells.ReleaseDispatch();
row.ReleaseDispatch();
rows.ReleaseDispatch();
range1.ReleaseDispatch();
range.ReleaseDispatch();
table.ReleaseDispatch();
tables.ReleaseDispatch();
docs.ReleaseDispatch();
doc.ReleaseDispatch();
pgraph.ReleaseDispatch();
pgraphs.ReleaseDispatch();
wordApp.Quit(vFalse,vLong,vLong);
wordApp.ReleaseDispatch();
CoUninitialize();
}
我的code存在一个问题,为什么我调用段落paragraph对象的GetStyle()方法后,word进程就退不出去了呢?位置在(Q1)处,已被注释掉的行。这都给我整晕了!
解决方案1:
pgraph.GetStyle()返回的VARIANT里包含的是一个IDispatch*,所以里面的IDispatch*已经AddRef,由于楼主没有对其Release,所以Word不能退出。
至于楼主上面那样修改后,用COleVariant的构造函数来将VARIANT包装进去,以期望用COleVariant的析构来释放它,不过在COleVariant中用::VariantCopy来将GetStyle()返回的VARIANT复制了一份,由于是VT_DISPATCH,所以::VariantCopy中再一次调用了AddRef,所以ColeVariant的析构并没有其期望的作用。
既然楼主已经包装了Style,如下即可:
for( ... )
{
...
style = pgraph.GetStyle().pdispVal;
...
}
...
style.ReleaseDispatch();
很大可能性是引用计数的原因
你试着跳到包装类中跟踪一下
循环里面创建一个变量,负责自动清除GetStyle获得的资源
COleVariant varStyle=pgraph.GetStyle();
不太清楚,不过个人认为如果服务器不退出,是因为组件的引用计数还没有变为0,也就是说还有组件没有释放,也就是说还有组件的接口没有被Release导致这个组件没有被释放。
我觉得你可以尽量少建立一些对象,来测试测试。