Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/excel/28.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Excel 办公自动化与Windows 7和Office 2007挂起_Excel_Multithreading_Delphi_Automation - Fatal编程技术网

Excel 办公自动化与Windows 7和Office 2007挂起

Excel 办公自动化与Windows 7和Office 2007挂起,excel,multithreading,delphi,automation,Excel,Multithreading,Delphi,Automation,我有一个Delphi XE8程序,我使用Office Automation构建Excel文件。建筑需要几秒钟,所以我把这项工作放在后台线程中,这样我的程序将保持响应,我可以处理取消请求 我是这样设置的: TTask.Run( procedure var oXL, oSheet, o2Sheet, oRng, VArray : Variant; begin oXL := CreateOleObject('Excel.Application'); oXL.Visi

我有一个Delphi XE8程序,我使用Office Automation构建Excel文件。建筑需要几秒钟,所以我把这项工作放在后台线程中,这样我的程序将保持响应,我可以处理取消请求

我是这样设置的:

TTask.Run(
  procedure
  var
    oXL, oSheet, o2Sheet, oRng, VArray : Variant;
  begin
    oXL := CreateOleObject('Excel.Application');
    oXL.Visible := False;
    oXL.DisplayAlerts := false;

    ... (all the processing to build the Excel file)

    oXL.Application.Workbooks[1].SaveAs(ExcelFilename, 51 { = xlWorkbookDefault } );
    oXL.Workbooks.Close;
    oXL.Application.Quit;
    oXL := Unassigned;
  end
);
这段代码运行得非常好,正是我想要的。它将Excel工作簿创建为后台任务,完成后从任务返回到主线程,并且应用程序保持响应

我觉得一切都很好。它与Office 2016一起在我的Windows 10计算机上运行。我有几个用户也在他们的计算机上成功地运行了它

但是我有一个用户的报告,程序在线程中挂起。我能做一些测试。当代码没有在他的机器上的线程中运行时,它工作得很好(当然,应用程序不再保持响应,我无法处理取消请求)

我能说的关于用户机器的唯一不同之处是他们运行的是Windows7和Office2007

我不是100%肯定办公自动化是线程安全的。我是否可以将其全部放在一个线程中,并理解一些自动化命令(哪些命令?)可能需要同步?如果它不是线程安全的,那么在生成Excel文件时,我如何保持应用程序的响应性


Windows 7与Windows 10上的Office自动化或Office 2007与Office 2016之间的差异是否会导致旧版本中的任务失败?如果是这样,是否有解决方法?

明显的缺陷是没有在线程中初始化COM。调用
CoInitialize
CoInitializeEx

从后台线程自动化Excel当然没有问题。你正在尝试的是可能的。可以想象,您没有显示的代码中存在bug,但缺少COM初始化是问题代码中唯一可以看到的错误


当然,当您不控制线程的生命周期时,COM初始化并不容易。线程库创建线程,您不知道该线程中已经运行了什么。如果我是你,我会显式地创建线程,并避免线程库中基于任务的方法

该线程仅运行Excel文件的构建。这并不是因为我的代码中有bug,因为只输入CreateOleObject语句和Close/Quit语句,而忽略其他所有语句会产生相同的结果。在我的问题中,我没有注意到的可能重要(也可能不重要)是,如果我将CreateOleObject和Close/Quit对象放入同步语句中,那么它可以在用户的机器上工作。当然,这只会让它再次在主线程中运行。这肯定是代码中的一个bug。始终怀疑自己的代码高于一切。正如我所说,可见的一个大错误是您没有初始化COM。在VCL应用程序中,COM是在主线程上初始化的。从技术上讲,这不是我代码中的错误。这是一个bug,因为我在代码中遗漏了一些内容。:-)省略基本代码是错误的,就像包含错误代码一样;对我的任务的声明,并更新了上面的问题以显示它。代码在我的机器和其他几个用户机器上仍然可以正常工作。我在有Windows7和Office2007的用户机器上测试了它,办公自动化仍然挂起。所以我的问题仍然没有解决,真正的代码肯定不是51。如果有,您必须停止使用magic常量,并定义适当的常量。@DavidFefferman-我必须搜索web以找到要使用的代码(xlWorkbookDefault)它的价值是什么,因为Delphi XE8 Pro包中不包含office automation常量。请在代码中定义它们。office automation常量在Delphi导入单位中定义(请参阅Excel2010.pas,在$(BDSDIR)\OCX\Servers文件夹中)。它被定义为
xlWorkbookDefault=$00000033,这是应该如何在代码中定义它。作为将来的参考,您可以使用Components->import Component导入Excel类型库,它创建的Delphi单元将包含您需要的所有定义,并且您可以将其用作参考,而不是搜索web。注意这一点也很重要,尽管我假设您不在这里执行此操作,您无法在登录用户之外自动执行Office应用程序(例如,无法从服务或未作为当前登录用户运行的计划任务中执行)。除了没有加载用户配置文件之外,最大的问题是,有时Office应用程序会显示一个模式对话框,任何人都无法看到或单击它。这将导致自动办公应用程序挂起。