“呼叫被被呼叫者拒绝”是您在 Word 处于交互状态(即显示对话框)时总是得到的。这不仅限于 Word。 Excel 也会发生这种情况,例如当用户编辑单元格时。它也不必在用户界面中很明显。当您开始编辑单元格,将焦点移到另一个应用程序并返回 Excel 时,UI 不会给您任何提示,但它仍处于“交互”模式,并将拒绝自动呼叫,并显示“呼叫被被呼叫者拒绝”错误。
因此,基本上,当您将 Word 与用户交互(而不仅仅是在后台进程中使用 Word)自动化时,您应该准备好获取和处理这些错误。
编辑
如果您想在调用任何其他 COM 方法之前知道 Excel 或 Word 是否处于交互模式:只需询问 COM 服务器是否“就绪”:
Result := _GetActiveOleObject('Excel.Application');
try
aSharedInstance := not VarIsClear(Result);
if aSharedInstance then
Version := Result.Version; // If this produces an exception, then use a dedicated instance.
// In case checking the version does not produce an exception, but Excel still isn't
// ready, we'll check that as well.
// By the way, for some unclear reason, partial evaluation does not work on .Ready,
// so we'll do it like this:
if aSharedInstance and (StrToIntDef(StringBefore('.', Version), 0) >= EXCEL_VERSION_2002) then
aSharedInstance := Result.Ready;
except
aSharedInstance := False;
end;
if not aSharedInstance then
Result := CreateOleObject('Excel.Application');
更新
显然 Word 没有“就绪”属性(谁说微软是一致的?)。在这种情况下,您需要在实际调用之前调用一个简单(且快速)的属性,并假设当它引发异常时,Word 尚未准备好,从而自己确定它的就绪状态。在上面的示例中,版本是在 Ready 属性之前检索的。如果这引发了异常,我们只是假设应用程序(在本例中为 Excel)尚未准备好并相应地继续。
类似的东西:
while Tries <= MaxTries do
try
Version := Word.Version;
Tries := MaxTries + 1; // Indicate success
Word.TheCallYouReallyWantToDo;
except
Inc(Tries);
sleep(0);
end;
注意 Word.Version 确实不会在对话框打开时抛出异常,因此这对于确定 Word 是否已准备好是没有用的。 :( 你必须试验才能找到一个。