确定Excel工作簿何时closures了Delphi

以下代码打开“app”参数指定的文档,然后等待,直到特定的文档被closures。 这适用于所有文档types,除非您打开Excel工作簿并打开另一个Excel工作簿。 代码认为该文档实际上仍处于打开状态时已closures。 我将如何解决这个问题?

procedure RunAppAndWAit( a: TApplication; app, par, verb: string); var seinfo: tshellexecuteinfo; exitcode: dword; begin fillchar( seinfo, sizeof( seinfo), 0); seinfo.cbsize := sizeof( tshellexecuteinfo); with seinfo do begin fmask := see_mask_nocloseprocess; wnd := a.Handle; lpfile := pchar( app); lpDirectory := pchar( ExtractFileDir( app)); lpParameters := pchar( par); lpVerb := pchar( verb); nshow := sw_shownormal; end; if ShellExecuteEx( @seinfo) then begin repeat a.ProcessMessages; GetExitCodeProcess( seinfo.hprocess, exitcode); until ( exitcode <> still_active) or a.terminated; end else sshowmessage( 'Unable to open ' + app); end; 

您的尝试只适用于在启动文档的同一过程中打开文档的应用程序。

许多应用程序不再以这种方式工作:启动文档的进程将文档传递到显示/编辑它的另一个进程,并且启动进程死亡。

您将需要find一个支持事件callback的API(在这种情况下,对于Excel,很可能是Excel公开的COM API),可以让您更仔细地观察Excel实际上对文档执行的操作。

使用此API打开文档,注册文档closures时调用的事件,等待事件,然后closures。

这不是很漂亮,可能不如你想的那么可靠,但是你可以循环(或者更好地使用一个计时器事件?)调用Windows EnumWindows函数来寻找标题栏,这个标题栏与你希望Excel显示的内容相符文件。 (显然,这是一个Excel特定的解决scheme。)

例如,查找包含单词“Excel”和文件名的标题栏,这是Excel在标题栏中显示的内容。

这种方法可能存在漏洞,使其变得脆弱。 事实上,由于我不认为这个解决scheme特别强大,所以我有点犹豫。 但是,如果你没有其他办法来解决你的问题,这可能工作…

谷歌“EnumWindows Delphi”示例代码。

… …进一步思考,下面是另一种方式。 正如Jeroen指出的,你可以使用API​​到Excel。 如果你正在做很多这样的调用,那么把CreateOLEObject和unAssigned赋值放在函数外面可能会减less重量。 (你需要一些尝试…除了块,以防Excel不再运行等)。这个解决scheme也是Excel特有的,笨拙的,IMO。 我不知道是否可能有情况(如文件,在Excel中打开对话框?),这将导致这将返回错误的结果。

所以,基本上,我说,这里有两个相对较弱的方法是特定于Excel,可能并不总是工作。 (当我这样说的时候,我几乎宁愿删除整个这个post……但是,也许会给你一些关于如何继续的想法。)

这段代码没有经过testing,但过去类似的代码已经为我工作了:

  uses ComObj; function FindWorkbook( Workbookname: String):boolean; var ExcelOLE: Variant; WorkbookNumber: Integer; begin Result := FALSE; ExcelOLE := CreateOLEObject('Excel.Application'); try for WorkbookNumber := 1 to ExcelOLE.Workbooks.Count do if UpperCase(WorkbookName) = UpperCase(ExcelOLE.Workbooks[WorkbookNumber].Name) then Result := TRUE; finally ExcelOLE := unAssigned; end; end;