打开Excel窗口会中断将数据从C#写入Excel

打开Excel窗口会中断将数据从C#写入Excel,c#,.net,excel,excel-interop,C#,.net,Excel,Excel Interop,当我的C#程序将数据连续写入Excel电子表格时,如果最终用户单击右上菜单并打开 Excel选项窗口,这会导致以下异常: System.Runtime.InteropServices.ComeException与HRESULT:0x800AC472 这会中断数据写入电子表格 理想情况下,应该允许用户这样做,而不会导致异常 我找到的唯一解决此错误代码的方法是循环并等待异常消失: 这实际上会挂起应用程序,数据不会写入Excel,用户对此问题一无所知 我想在写入Excel时禁用其主菜单,但找不到有关如

当我的C#程序将数据连续写入Excel电子表格时,如果最终用户单击右上菜单并打开 Excel选项窗口,这会导致以下异常:

System.Runtime.InteropServices.ComeException与HRESULT:0x800AC472

这会中断数据写入电子表格

理想情况下,应该允许用户这样做,而不会导致异常

我找到的唯一解决此错误代码的方法是循环并等待异常消失: 这实际上会挂起应用程序,数据不会写入Excel,用户对此问题一无所知

我想在写入Excel时禁用其主菜单,但找不到有关如何执行此操作的参考

我的应用程序支持Excel 2000到2013

以下是如何重现该问题:
  • 使用Windows桌面的Visual Studio Express 2013,在64位Windows 7上使用Excel 2007创建新的Visual C#Console应用程序项目

  • 添加对“Microsoft ExceL 12.0对象库”(用于ExceL)和“System.Windows.Forms”(用于messagebox)的引用

    以下是完整的代码:

      using System;
      using System.Collections.Generic;
      using System.Linq;
      using System.Text;
      using System.Threading.Tasks;
      using System.Threading.Tasks;
      using System.Threading; // for sleep
      using System.IO;
      using System.Runtime.InteropServices;
      using System.Reflection;
      using Microsoft.Win32;
      using Excel = Microsoft.Office.Interop.Excel; 
    
      namespace ConsoleApplication1
      {
          class Program
          {
              static void Main(string[] args)
              {
                  int i = 3; // there is a split pane at row two
                  Excel.Application xlApp;
                  Excel.Workbook xlWorkBook;
                  Excel.Worksheet xlWorkSheet;
    
                  try 
                  { 
                      object misValue = System.Reflection.Missing.Value;
    
                      xlApp = new Excel.Application();
                      xlApp.Visible = false;
                      xlWorkBook = xlApp.Workbooks.Add(misValue);
    
                      xlApp.Visible = true;
                      xlWorkSheet = (Excel.Worksheet)xlWorkBook.Worksheets.get_Item(1);
                      // next 2 lines for split pane in Excel:
                      xlWorkSheet.Application.ActiveWindow.SplitRow = 2; 
                      xlWorkSheet.Application.ActiveWindow.FreezePanes = true;
                      xlWorkSheet.Cells[1, 1] = "Now open the";
                      xlWorkSheet.Cells[2, 1] = "Excel Options window";
                  }
                  catch (System.Runtime.InteropServices.COMException)
                  {
                      System.Windows.Forms.MessageBox.Show("Microsoft Excel does not seem to be installed on this computer any longer (although there are still registry entries for it). Please save to a .tem file. (1)");
                        return;
                  }
                  catch (Exception)
                  {
                      System.Windows.Forms.MessageBox.Show("Microsoft Excel does not seem to be installed on this computer any longer (although there are still registry entries for it). Please save to a .tem file. (2)");
                      return;
                  }
    
                  while(i < 65000)
                  {
                      i++;
    
                      try
                      {
                          xlWorkSheet.Cells[i, 1] = i.ToString();
                          Thread.Sleep(1000);
                      }
                      catch (System.Runtime.InteropServices.COMException)
                      {
                          System.Windows.Forms.MessageBox.Show("All right, what do I do here?");
                      }
                      catch (Exception) 
                      {
                          System.Windows.Forms.MessageBox.Show("Something else happened.");    
                      }
                  }
    
                  Console.ReadLine(); //Pause
              }
          }
      }
    
    
    使用系统;
    使用System.Collections.Generic;
    使用System.Linq;
    使用系统文本;
    使用System.Threading.Tasks;
    使用System.Threading.Tasks;
    使用System.Threading;//睡觉
    使用System.IO;
    使用System.Runtime.InteropServices;
    运用系统反思;
    使用Microsoft.Win32;
    使用Excel=Microsoft.Office.Interop.Excel;
    命名空间控制台应用程序1
    {
    班级计划
    {
    静态void Main(字符串[]参数)
    {
    int i=3;//第二行有一个拆分窗格
    Excel.applicationxlapp;
    Excel.工作簿;
    Excel工作表;
    尝试
    { 
    对象错误值=System.Reflection.Missing.Value;
    xlApp=new Excel.Application();
    xlApp.Visible=false;
    xlWorkBook=xlApp.Workbooks.Add(错误值);
    xlApp.Visible=true;
    xlWorkSheet=(Excel.Worksheet)xlWorkBook.Worksheets.get_项(1);
    //Excel中拆分窗格的下两行:
    xlWorkSheet.Application.ActiveWindow.SplitRow=2;
    xlWorkSheet.Application.ActiveWindow.FreezePanes=true;
    xlWorkSheet.Cells[1,1]=“现在打开工作表”;
    xlWorkSheet.Cells[2,1]=“Excel选项窗口”;
    }
    捕获(System.Runtime.InteropServices.COMException)
    {
    System.Windows.Forms.MessageBox.Show(“此计算机上似乎不再安装Microsoft Excel(尽管仍有它的注册表项)。请保存到.tem文件。(1)”;
    返回;
    }
    捕获(例外)
    {
    System.Windows.Forms.MessageBox.Show(“此计算机上似乎不再安装Microsoft Excel(尽管仍有它的注册表项)。请保存到.tem文件。(2)”;
    返回;
    }
    而(i<65000)
    {
    i++;
    尝试
    {
    xlWorkSheet.Cells[i,1]=i.ToString();
    睡眠(1000);
    }
    捕获(System.Runtime.InteropServices.COMException)
    {
    System.Windows.Forms.MessageBox.Show(“好吧,我在这里做什么?”);
    }
    捕获(例外)
    {
    System.Windows.Forms.MessageBox.Show(“发生了其他事情”);
    }
    }
    Console.ReadLine();//暂停
    }
    }
    }
    
  • 打开应用程序,Excel出现,数据写入其中。从菜单中打开Excel选项对话框窗口,弹出错误:

    mscorlib.dll中发生“System.Runtime.InteropServices.COMException”类型的异常,在托管/本机边界之前未处理该异常
    其他信息:来自HRESULT的异常:0x800AC472

  • 单击“继续”,我的消息框“好的,我在这里做什么?”出现

请告知

致以最良好的祝愿,
Bertrand

自动化Excel并与它的“perculiarities”搏斗的一个可能的替代方法是使用OpenXmlWriter编写器(DocumentFormat.OpenXml.OpenXmlWriter)写出文件

这有点棘手,但在处理超过100万行的床单时不会出一身冷汗


我们终于在这个问题上找到了Microsoft支持部门。他们的最后答复是:

我能够重现这个问题。我对此做了进一步的研究 发现这种行为是预期的,也是设计的。这 由于Excel正忙,引发异常0x800AC472–VBA_E_IGNORE 并且不会为任何对象模型调用提供服务。这是其中一个例子 关于这一点的讨论。 我看到的解决方法是显式捕获此异常并重试 一段时间后,直到你的预期行动完成

由于我们无法理解用户的想法,用户可能决定打开一个窗口或记笔记,而没有意识到软件已停止记录(如果您掩盖错误),因此我们决定使用以下方法解决此问题:

 xlWorkSheet.EnableSelection = Microsoft.Office.Interop.Excel.XlEnableSelection.xlNoSelection;

锁定Excel窗口UI。我们提供了一个明显的“解锁”按钮,但当用户单击它时,消息框中会严厉警告他“您想继续吗?”

我成功地做了一个目标excel文件的临时副本,然后用代码打开它

那样我
 xlWorkSheet.EnableSelection = Microsoft.Office.Interop.Excel.XlEnableSelection.xlNoSelection;
private void x(string str)
{
    while (this.Application.Interactive == true)
    {
        // If Excel is currently busy, try until go thru
        SetAppInactive();
    }

    // now writing the data is protected from any user interaption
    try
    {
        for (int i = 1; i < 2000; i++)
        {
            sh.Cells[i, 1].Value2 = str;
        }
    }
    finally
    {
        // don't forget to turn it on again
        this.Application.Interactive = true;
    }
}
private void SetAppInactive()
{
    try
    {
        this.Application.Interactive = false;
    }
    catch
    {
    }
}
bool failed = false;
do
{
    try
    {
        // Call goes here
        failed = false;
    }
    catch (System.Runtime.InteropServices.COMException e)
    {
        failed = true;
    }
    System.Threading.Thread.Sleep(10);
} while (failed);