excel - 运行delphi客户端自动化程序后excel.exe保持加载状态的原因是什么?

标签 excel delphi office-automation

我编写了一个 Delphi 程序,该程序从单个 .XLS 文件的多个不同电子表格中提取数据并将其合并到文本文件中以供以后处理。它是一个 Delphi 7 控制台程序。

最相关的代码片段的摘录将向您表明,显然,我的程序表现得非常好,或者至少达到了它需要的程度。

uses ...  ActiveX, ComObj ... ;

procedure Fatal(s:string);
  ...
  Halt(1);

var ExcelApp:Variant; (* global var *)

begin (* main program block *)
  coInitialize(nil);
  ExcelApp:=CreateOleObject('Excel.Application');
  try
    ExcelApp.Visible:=False;
    ExcelApp.WorkBooks.Open(ExcelFileName);
  ...
    XLSSheet := ExcelApp.Worksheets[ExcelSheetName];
  ...
    try
      XLSRange := XLSSheet.Range[ExcelRangeName];
    except
      Fatal('Range "'+ExcelRangeName+'" not found');
    end;
    if VarIsNull(XLSRange) then Fatal('Range '+ExcelRangeName+' not found');
    for row:=XLSRange.Row to XLSRange.Rows[XLSRange.Rows.Count].Row do
      for col:=XLSRange.Column to XLSRange.Columns[XLSRange.Columns.Count].Column do
        CellValue:=XLSSheet.Cells[Row,Col].Value;
        ...
        if CellValue<>'' then ...
        ...
    ExcelApp.Workbooks.Close;
    ...
  finally
    ExcelApp.Quit;
    coUninitialize;
  end;   
end.

有时,当程序退出时,XLS 仍保持锁定状态。查看任务管理器,我看到客户端程序运行时启动的 Excel.exe 进程仍在运行,即使客户端程序已退出并成功卸载。

您是否知道这种行为的常见嫌疑人是什么?知道在哪里寻找在客户端执行时始终卸载 Excel 的信息吗?

最佳答案

您需要发布ExcelApp 变体。它的引用计数仍然为 1,因此 Excel 并未完全关闭。

将其添加到您的代码中(标记行):

finally
  ExcelApp.Quit;
  ExcelApp := Unassigned;        // Add this line
  coUninitialize;
end;  

这里是一些简单的代码来重现问题并测试解决方案:

// Add two buttons to a form, and declare a private form field. 
// Add OnClick handlers to the two buttons, and use the code provided. 
// Run the app, and click Button1. Wait until Excel is shown, and then click
// Button2 to close it. See the comments in the Button2Click event handler.
type
  TForm1=class(TForm)
    Button1: TButton;
    Button2: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    ExcelApp: Variant;
  end;

implementation

uses
  ComObj;

procedure TForm1.Button1Click(Sender: TObject);
begin
  ExcelApp := CreateOleObject('Excel.Application');
  ExcelApp.Visible := True;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  ExcelApp.Visible := False;
  ExcelApp.Quit;

  // Leave the next line commented, run the app, and click the button.
  // After exiting your app NORMALLY, check Task Manager processes, and you'll
  // see an instance of Excel.exe still running, even though it's not
  // in the Applications tab. 
  //
  // Do an "end process" in Task Manager to remove the orphaned instance 
  // of Excel.exe left from the above. Uncomment the next line of code
  // and repeat the process, again closing your app normally after clicking
  // Button2. You'll note that Excel.exe is no longer in
  // Task Manager Processes after closing your app.

  // ExcelApp := Unassigned;
end;

end.

关于excel - 运行delphi客户端自动化程序后excel.exe保持加载状态的原因是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12304422/

相关文章:

excel - 我们如何在声明语句中使用字符串变量?

multithreading - 在线程中使用这段代码有什么问题吗? (德尔福)

algorithm - 解析器解释器编程

com - 使用 Powershell 将 Excel 工作表从一个工作簿复制到另一个工作簿

Excel VBA SendKeys 不会导致 IE 9 保存下载

excel添加保存内部数据?

excel - 从命令行或批处理文件运行 Excel 宏的方法?

excel - VBA:使用 Excel 查询 Access。为什么这么慢?

vba - 使用 Document.Paragraphs.Add() 创建多个 Word 段落

delphi - 在 Delphi 中显示资源管理器菜单