C#からExcelへのデータ書き込みがExcelウィンドウを開くと中断される

私のC#プログラムがExcelスプレッドシートに継続的にデータを書き込んでいるときに、エンドユーザーが右上のメニューをクリックして Excel オプション] ウィンドウを開くと、HRESULT: 0x800AC472 の System.Runtime.InteropServices.COMException が発生し、スプレッドシートへのデータ書き込みが中断されます。 が発生し、スプレッドシートにデータが書き込まれなくなります。

理想的には、例外を発生させることなく、ユーザーがこれを実行できるようにする必要があります。

このエラーコードに対する唯一の解決策は、例外がなくなるまでループして待つことでした。 https://stackoverflow.com/questions/1952759/exception-from-hresult-0x800ac472 この場合、アプリはハングアップし、データはExcelに書き込まれず、ユーザーは問題について何もわからないままです。

Excelへの書き込み中にExcelのメインメニューを無効にすることも考えましたが、その方法についての参考文献を見つけることができません。

私のアプリはExcel 2000から2013まで対応しています。

以下、問題の再現方法です。

Visual Studio Express 2013 for Windows Desktop、.NET 4.5.1 on Windows 7 64-bit with Excel 2007を使用しています。

新しいVisual C#コンソールアプリケーションプロジェクトを作成します。

Microsoft ExceL 12.0 Object Library" (Excel用) と "System.Windows.Forms" (メッセージボックス用) への参照を追加します。

以下は、そのコードの一部です。

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
        }
    }
}

アプリを起動すると、Excelが表示され、データが書き込まれます。メニューからExcelのオプションダイアログウィンドウを開くと、エラーがポップアップ表示されます。

'System.Runtime.InteropServices.COMException' 型の例外が mscorlib.dll で発生し、管理/ネイティブ境界の前に処理されませんでした。

追加情報です。HRESULTからの例外:0x800AC472

続行」をクリックすると、メッセージボックス「All right, what do I do here?"」が表示されます。

アドバイスをお願いします。

よろしくお願いします。 ベルトラン

ソリューション

私たちはこの問題で、ついにマイクロソフトのサポートまで行きました。彼らの最終的な回答は

この問題を再現することができます。この件についてさらに調査したところ この動作は予期されたものであり、デザインによるものであることがわかりました。 この 0x800AC472 - VBA_E_IGNORE という例外は、Excel がビジー状態であるために発生します。 オブジェクトモデルの呼び出しを処理しないためです。以下は、その一つです。 gt;このことについて述べている議論です。 http://social.msdn.microsoft.com/Forums/vstudio/en-US/9168f9f2-e5bc-4535-8d7d-4e374ab8ff09/hresult-800ac472-from-set-operations-in-excel?forum=vsto 私が見た回避策は、この例外を明示的にキャッチして、しばらくしてから再試行することです。 意図した動作が完了するまで、しばらくしてから再試行することです。

ソフトがロギングを停止したことに気づかず、ウィンドウを開いたり、メモを取ったりするユーザーの心理は読めないので(エラーを隠せば)、私たちは、この例外を使用して回避することにしました。

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

を使ってExcelウィンドウのUIをロックすることにしました。明らかな "unlock" ボタンを提供しますが、ユーザーがそれをクリックすると、メッセージボックスで "Do you wish to continue?&quot とともに厳重に警告されます。

解説 (0)
xlApp = new Excel.Application();
xlApp.Interactive = false;
解説 (1)

Excelを自動化し、その特殊性と格闘する代わりに、OpenXmlWriterライター(DocumentFormat.OpenXml.OpenXmlWriter)を使ってファイルを書き出すことも可能です。

これは少し厄介ですが、100万行のシートを問題なく処理できます。

MSDNのOpenXmlドキュメント

解説 (1)