检测Excel文件是否已关闭

时间:2010-05-01 00:41:43

标签: c# .net

我花了过去3个小时在网上搜索无效的答案,所以我希望你能帮助我。我正在编写一个自动化Excel的应用程序。该应用程序有一个“显示/隐藏Excel工作表”的选项,以便您可以查看它,进行任何最终更改等等。

关闭应用程序自然会关闭Excel的实例,但是,有人可能会直接退出Excel,而不用考虑。这打破了我的应用程序,我似乎无法找到“检查相同的工作簿是否仍然打开,如果没有,重新打开它”,然后保存它

我已经尝试了各种各样的事情:检查Excel应用程序是否为空(当它是!= null它将正确保存,但当它“是”为空时(或至少,除了!= null之外它赢了)甚至打到了断点,所以我完全迷失了:(

请帮忙吗?

编辑:感谢所有回复,我很快就会回复。

AJ让我编辑我的问题以提供更多信息:我使用来自C#应用程序的COM Interop自动化Excel。该应用程序允许用户输入某些统计信息,然后在Excel中进行更新。有一个按钮允许显示/隐藏Excel,以防有人想要检查工作表中的任何其他信息如果有人直接退出Excel,那么仍然可以使用显示/隐藏按钮(它显示Excel应用程序没有加载工作簿)并且相同的Excel实例仍显示在任务管理器中,但是当我单击“保存”按钮时。

我在上次稍微不同的地方添加了一个try / catch(上次没有捕获任何错误,现在它捕获了两个错误:

HRESULT的异常:0x800401A8

调用的对象已与其客户端断开连接。 (来自HRESULT的异常:0x80010108(RPC_E_DISCONNECTED))

所以基本上我似乎需要再次“重新连接”这两个,虽然在网上查看新的错误消息似乎并不表明它可能是一个问题。

我想知道是否最好将所有值存储在字符串中(有时在应用程序失败的情况下写入临时文件),然后在应用程序关闭时最终将它们推送到Excel中?

7 个答案:

答案 0 :(得分:6)

Microsoft.Office.Interop.Excel.Application实际上有一个您使用的事件,它在工作簿关闭之前被触发。即使其他人在Excel中关闭工作簿,也会被解雇。该事件称为WorkbookBeforeClose()。

m_app = new Microsoft.Office.Interop.Excel.Application() { Visible = false };
m_app.WorkbookBeforeClose += new AppEvents_WorkbookBeforeCloseEventHandler(m_app_WorkbookBeforeClose);
m_workbook = m_app.Workbooks.Open(); // removing all arguements here for simplicity

// event handler code
void m_app_WorkbookBeforeClose(Workbook Wb, ref bool Cancel)
{
  // making sure it is the same file that I opened
  if (Wb.FullName == m_workbook.FullName)
  {
    m_workbook = null;
  }
}

// when your app is closing
public void Close()
{
  if (m_workbook != null)
  {
    m_workbook.Close(Type.Missing, Type.Missing, Type.Missing);
  }
  m_app.Quit();         
}

答案 1 :(得分:2)

  

我尝试过各种各样的事情:   检查Excel应用程序是否是   null(当它是!= null时它会保存   正确,但当它“是”null(或   至少,除了!= null之外的其他东西   它甚至不会打破断点   我完全迷失了:(

测试可以这样完成:

if ( excelApp == null) {
  ; //set breakpoint here during execution to see if it IS null
}

编辑:

Type wheresExcel = typeof(excelApp); //this is going to execute if the object has not been GC'd

/编辑:

所以你的代码看起来像是:

if ( excelApp != null ) {
  doSomething();
}

然后为什么不这样做:

if ( excelApp == null ) {
  startExcel();
  addWorksheetToExcelInstance();
}
doSomething();

答案 2 :(得分:1)

我刚刚经历并解决了这个问题,虽然在这个问题上已经太晚了,但我只是想在这里添加我的修复,这可能会对某人有所帮助。

问题:在关闭Excel工作表/工作簿之前,我正在关闭Excel应用程序对象。因此,它将工作表/工作簿对象与excel应用程序对象分离。

解决方案:关闭Excel应用程序对象之前关闭excel工作表/工作簿,或者从工作表到工作簿再到Excel应用程序。

示例:xlwks.Close(); xlwks = null; xlwbk = null; xlapp = null;

答案 3 :(得分:0)

如何使用FindWindow API查看该应用是否仍然可见?

答案 4 :(得分:0)

没有良好的方式(阅读:可靠+健壮),但有人在msdn社交网站上提出了a reasonable workaround here,这可能会为您提供帮助。

文章讨论了使用子类来挂钩窗口。它还引用了一个article on the microsoft support site,它更广泛地讨论了C#和.Net的子类化。

我使用的唯一其他替代方案是一个非常俗气的解决方法 - 我会允许Excel显示,但我将自己的留在顶部的表单放在标题栏+按钮(不推荐)。

修改

以防万一不清楚 - 我不建议你创建一个加载项,但是类似的子类化方法可能会在自动化时影响Excel的行为。我假设您使用互操作来'自动化excel'。

答案 5 :(得分:0)

为什么在保存之前需要重新打开工作簿?

将保存包裹在try...catch块中 - 如果它有效,那么你很好,如果没有,你可以在catch块中以任何你认为合适的方式处理它。

答案 6 :(得分:0)

真的很晚但是每次我在发布实际工作簿之前意外发布应用程序时都会发生这种情况,所以只需先发布工作簿