delphi 使用自动化和Excel应用程序,准备

5us2dqdw  于 2023-11-18  发布在  其他
关注(0)|答案(1)|浏览(104)

我试图从Win32 Delphi应用程序中自动化Excel。我不得不在代码中放入numetric Sleep(),以便Excel(更有可能)为下一个自动化命令做好准备。通常在打开文件后,但在许多其他情况下也是如此。当然,这并不理想,所以我正在寻找一种方法来检查Excel是否准备好了。
我找到了属性Application.Ready,但在我的用例中它从来没有返回false。也许是Application.Ready只在Excel等待用户处理av messagebox时返回false,以及类似的情况?
是否有其他方法可以使用自动化来确定Excel是否准备好了?
代码示例:

procedure CopyFromExcelSheet;
var
  ExcelApp: OleVariant;
  WorkSheet: OleVariant;
begin
  ExcelApp := CreateOleObject('Excel.Application');
  ExcelApp.Visible := False;
  ExcelApp.Workbooks.Open(<Filename>);

  GiveExcelSomeTime(ExcelApp, 600);

  WorkSheet := ExcelApp.Workbooks[1].Sheets[1];
  WorkSheet.Activate;
  
  GiveExcelSomeTime(ExcelApp, 300);

  WorkSheet.UsedRange.Copy;
  etc.
end;


procedure GiveExcelSomeTime(AApp: OleVariant; ATime: Integer);
var
  LMillisec: Integer;
begin
  LMillisec := 0;

  while not AApp.Ready do
  begin
    Sleep(100);
    LMillisec := LMillisec + 100;
    if LMillisec > ATime * 2 then
      Break;
  end;

  //This one I have never seen:
  if LMillisec > 0 then
    ShowMessage('Waited '+IntToStr(LMillisec)+' for Excel');

  if LMillisec = 0 then
    Sleep(ATime);
end;

字符串

4szc88ey

4szc88ey1#

看起来你可以从实现Ole消息过滤器中受益。我曾经遇到过同样的问题,我发现了这个链接。
How to extend existing interface IMessageFilter with TInterfacedObject?
然后我实现了下面的单元,在执行自动化操作时调用IOleMessageFilter.RegisterFilter,完成后调用IOleMessageFilter.RevokeFilter。

unit Rgd.OleMessageFilter;

{Usage: IOleMessageFilter.RegisterFilter;
        IOleMessageFilter.RevokeFilter;

 You do not create an instance of IOleMessageFilter.  The class function IOleMessageFilter.RegisterFilter
 creates the instance, which is reference counted and is freed when revoked.

}

interface

uses WinApi.ActiveX, System.Classes, WinApi.Windows, System.SysUtils;

type
  IOleMessageFilter = class(TInterfacedObject, IMessageFilter)
  public
    {IOleMessageFilter interface...}
    function HandleInComingCall(dwCallType: Longint; htaskCaller: HTask; dwTickCount: Longint; lpInterfaceInfo: PInterfaceInfo): Longint; stdcall;
    function RetryRejectedCall(htaskCallee: HTask; dwTickCount: Longint; dwRejectType: Longint): Longint; stdcall;
    function MessagePending(htaskCallee: HTask; dwTickCount: Longint; dwPendingType: Longint): Longint; stdcall;
    {class functions to Register and Revoke...}
    class procedure RegisterFilter();
    class procedure RevokeFilter();
  end;

implementation

{TOleMessageFilter...}
function IOleMessageFilter.HandleInComingCall(dwCallType: Integer; htaskCaller: HTask; dwTickCount: Integer; lpInterfaceInfo: PInterfaceInfo): Longint;
begin
  Result := 0;
end;

function IOleMessageFilter.MessagePending(htaskCallee: HTask; dwTickCount, dwPendingType: Integer): Longint;
begin
  Result := 2 // PENDINGMSG_WAITDEFPROCESS
end;

function IOleMessageFilter.RetryRejectedCall(htaskCallee: HTask; dwTickCount, dwRejectType: Integer): Longint;
begin
  Result := -1;
  if dwRejectType = 2 then
  begin
    Result := 99;
  end;
end;

class procedure IOleMessageFilter.RegisterFilter;
var
  OldFilter, NewFilter: IMessageFilter;
begin
  OldFilter := nil;
  NewFilter := IOleMessageFilter.Create;
  CoRegisterMessageFilter(NewFilter, OldFilter);
end;

class procedure IOleMessageFilter.RevokeFilter;
var
  OldFilter, NewFilter: IMessageFilter;
begin
  OldFilter := nil;
  NewFilter := nil;
  CoRegisterMessageFilter(NewFilter, OldFilter);
end;

end.

字符串

相关问题