programing

Excel 창 열기로 인해 C#에서 Excel로 데이터 쓰기가 중단됨

itmemos 2023. 9. 4. 19:34
반응형

Excel 창 열기로 인해 C#에서 Excel로 데이터 쓰기가 중단됨

C# 프로그램이 Excel 스프레드시트에 계속 데이터를 쓰는 동안 최종 사용자가 오른쪽 상단 메뉴를 클릭하고 Excel 옵션 창을 열면 다음과 같은 예외가 발생합니다.

시스템. 런타임.Interop Services.HRESULT를 포함한 COME 예외: 0x800AC472

그러면 데이터가 스프레드시트에 기록되는 것이 중단됩니다.

이상적으로 사용자는 예외 없이 이 작업을 수행할 수 있어야 합니다.

이 오류 코드에 대한 유일한 해결책은 예외가 사라질 때까지 루프하고 기다리는 것이었습니다: HRESULT에서 예외: 0x800AC472는 앱을 효과적으로 중단시키고 데이터는 Excel에 기록되지 않으며 사용자는 문제에 대해 알지 못합니다.

엑셀에 글을 쓰면서 메인 메뉴를 비활성화할까 생각했는데, 어떻게 하는지 참고 자료를 찾을 수가 없습니다.

내 앱은 Excel 2000부터 2013까지 지원합니다.

문제를 재현하는 방법은 다음과 같습니다.

  • 윈도우즈 데스크톱용 Visual Studio Express 2013 사용,윈도우즈 7 64비트에서 NET 4.5.1(Excel 2007 포함), 새 Visual C# 콘솔 응용 프로그램 프로젝트를 생성합니다.

  • "Microsoft Excel 12.0 Object Library"(Excel의 경우) 및 "System"에 대한 참조를 추가합니다.창문들.양식"(메시지 상자용).

    전체 코드는 다음과 같습니다.

      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' 유형의 예외입니다. 운용 서비스입니다Interop 서비스.'했으며 관리 'COMEXception'의 mscorlib 이전에 .dll에서 발생했으며 관리/원본 경계 이전에 처리되지 않았습니다.
    : HRESULT에서 HRESULT 파일: 0x800AC472

  • 계속을 클릭하면 "좋아요, 여기서 뭘 해야 하나요?"라는 메시지 상자가 나타납니다.

조언 부탁드립니다.

베르트랑, 잘 부탁드립니다.

이 문제를 해결하기 위해 마이크로소프트 지원 서비스를 시작했습니다.이들의 최종 반응은 다음과 같습니다.

저는 그 문제를 재현할 수 있습니다.저는 이것에 대해 더 연구했고 이 행동이 의도적으로 기대된다는 것을 발견했습니다.예외: 0x800AC472 – VBA_E_IGNORE는 Excel이 사용 중이고 Object Model 호출을 처리하지 않기 때문에 느려집니다.여기 이것에 대해 이야기하는 토론 중 하나가 있습니다.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를 잠급니다.명백한 "잠금 해제" 버튼을 제공하지만 사용자가 이 버튼을 클릭하면 메시지 상자에 "계속하시겠습니까?"라는 경고가 표시됩니다.

Make Excel Interactive는 완벽한 솔루션입니다.유일한 문제는 사용자가 Excel에서 범위 선택이나 셀 편집과 같은 작업을 동시에 수행하는 경우입니다.예를 들어 코드가 다른 스레드에서 반환되어 계산 결과를 Excel에 기록하려고 합니다.이 문제를 피하기 위해 제가 제안하는 것은 다음과 같습니다.

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
    {
    }
}
xlApp = new Excel.Application();
xlApp.Interactive = false;

제가 성공적으로 한 일은 코드로 열기 전에 타겟 엑셀 파일의 임시 복사본을 만드는 것입니다.

그러면 원본 문서가 열려 있는지 여부와 관계없이 문서를 조작할 수 있습니다.

Excel을 자동화하고 Excel의 특이점과 씨름하는 방법 중 하나는 OpenXmlWriter(DocumentFormat)를 사용하여 파일을 쓰는 것입니다.OpenXml.OpenXmlWriter).

그것은 조금 까다롭지만 100만 줄 이상의 시트를 땀 한 방울 흘리지 않고 처리합니다.

MSDN의 OpenXml 문서

Interop은 크로스 스레드를 수행하기 때문에 여러 스레드에 의해 동일한 객체에 액세스할 수 있으며, 아래 코드가 작동하는 예외로 이어질 수 있습니다.

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);

언급URL : https://stackoverflow.com/questions/23808057/writing-data-from-c-sharp-to-excel-interrupted-by-opening-excel-window

반응형