MFC

MFC에서 Microsoft Excel 워크시트를 포함시키고 자동화하는 방법

디버그정 2008. 9. 10. 19:35

MFC에서 Microsoft Excel 워크시트를 포함시키고 자동화하는 방법

기술 자료 ID : 184663
마지막 검토 : 2007년 5월 15일 화요일
수정 : 5.0

요약

이 문서에서는 Microsoft Excel 워크시트를 SDI MFC 응용 프로그램의 View 개체에 포함시키는 방법을 설명합니다.

이 문서에는 워크시트를 포함시키고 일부 텍스트를 A1 셀에 추가하기 위한 단계별 지침뿐 아니라 각 단계를 설명하는 주석도 포함되어 있습니다.

이 문서에 나와 있는 예제 코드를 응용 프로그램에 붙여 넣을 수도 있지만 예제를 읽고 이해하는 것이 중요합니다.

추가 정보

Microsoft는 모든 보증(상품 및 특정 목적에의 적합성에 대한 묵시적인 보증을 포함하며 이에 제한되지 않음)을 배제하며 예를 보여주기 위한 목적으로만 이 프로그래밍 예제를 제공합니다. 본 문서의 내용은 프로시저를 작성하고 디버깅하는 데 사용되는 도구 및 여기서 설명하는 프로그래밍 언어에 익숙한 사용자를 대상으로 합니다. Microsoft 지원 담당자는 사용자에게 도움이 되도록 특정 프로시저에 대한 기능을 설명할 수 있지만 사용자의 특정 요구 사항에 맞도록 예제를 수정하여 추가 기능을 제공하거나 프로시저를 구성하지는 않습니다.

MFC 응용 프로그램을 만들려면 다음과 같이 하십시오.
1. AppWizard를 사용하여 "Embed_Excel"이라는 MFC AppWizard(EXE) 프로젝트를 새로 만듭니다.
2. 만들 응용 프로그램의 종류로 Single Document를 선택하고 포함할 복합 문서 지원의 형식으로 Container를 선택합니다. 다른 기본 설정은 모두 그대로 사용합니다.

다음과 같은 클래스가 생성됩니다.

Application: Embed_Excel.h의 CEmbed_ExcelApp와 Embed_Excel.cpp

Frame: MainFrm.h의 CMainFrame과 MainFrm.cpp

Document: Embed_ExcelDoc.h의 CEmbed_ExcelDoc와 Embed_ExcelDoc.cpp

View: Embed_ExcelView.h의 CEmbed_ExcelView와 Embed_ExcelView.cpp

Container Item: CntrItem.h의 CEmbed_ExcelCntrItem과 CntrItem.cpp
3. View 메뉴에서 ClassWizard를 누릅니다. Automation 탭을 누르고 Add Class를 누른 다음 From a Type Library를 선택합니다. Microsoft Excel type library를 찾고 해당 형식 라이브러리에 있는 모든 클래스를 프로젝트에 추가합니다. 형식 라이브러리는 Excel 97의 경우 Excel8.olb에 있고, Excel 2000의 경우 Excel9.olb에 있으며, Excel 2002 이상의 경우 Excel.exe에 있습니다.
4. CntrItem.h에 다음 줄을 추가합니다.
LPDISPATCH GetIDispatch();
					
5. 그런 다음 GetIDispatch 메서드를 CntrItem.cpp에 추가합니다.
   Sample Code
   -----------


      /*******************************************************************
      *   This method returns the IDispatch* for the application linked to
      *   this container.
      ********************************************************************/ 
      LPDISPATCH CEmbed_ExcelCntrItem::GetIDispatch()
      {
         //The this and m_lpObject pointers must be valid for this function
         //to work correctly. The m_lpObject is the IUnknown pointer to
         // this object.
         ASSERT_VALID(this);

         ASSERT(m_lpObject != NULL);

         LPUNKNOWN lpUnk = m_lpObject;

         //The embedded application must be running in order for the rest
         //of the function to work.
         Run();

         //QI for the IOleLink interface of m_lpObject.
         LPOLELINK lpOleLink = NULL;
         if (m_lpObject->QueryInterface(IID_IOleLink,
            (LPVOID FAR*)&lpOleLink) == NOERROR)
         {
            ASSERT(lpOleLink != NULL);
            lpUnk = NULL;

            //Retrieve the IUnknown interface to the linked application.
            if (lpOleLink->GetBoundSource(&lpUnk) != NOERROR)
            {
               TRACE0("Warning: Link is not connected!\n");
               lpOleLink->Release();
               return NULL;
            }
            ASSERT(lpUnk != NULL);
         }

         //QI for the IDispatch interface of the linked application.
         LPDISPATCH lpDispatch = NULL;
         if (lpUnk->QueryInterface(IID_IDispatch, (LPVOID FAR*)&lpDispatch)
            !=NOERROR)
         {
            TRACE0("Warning: does not support IDispatch!\n");
            return NULL;
         }

         //After assuring ourselves it is valid, return the IDispatch
         //interface to the caller.
         ASSERT(lpDispatch != NULL);
         return lpDispatch;
      }
					
6. Embed_ExcelView.h에 다음 줄을 추가합니다.
      void EmbedAutomateExcel();
					
7. 그런 다음 EmbedAutomateExcel 메서드를 Embed_ExcelView.cpp에 추가합니다.
Sample Code
-----------
      /********************************************************************
      *   This method encapsulates the process of embedding an Excel
      *   Worksheet in a View object and automating that worksheet to add
      *   some text to cell A1.
      ********************************************************************/ 
      void CEmbed_ExcelView::EmbedAutomateExcel()
      {
         //Change the cursor so the user knows something exciting is going
         //on.
         BeginWaitCursor();

         CEmbed_ExcelCntrItem* pItem = NULL;
         TRY
         {
            //Get the document associated with this view, and be sure it's
            //valid.
            CEmbed_ExcelDoc* pDoc = GetDocument();
            ASSERT_VALID(pDoc);

            //Create a new item associated with this document, and be sure
            //it's valid.
            pItem = new CEmbed_ExcelCntrItem(pDoc);
            ASSERT_VALID(pItem);

            // Get Class ID for Excel sheet.
            // This is used in creation.
            CLSID clsid;
            if(FAILED(::CLSIDFromProgID(L"Excel.sheet",&clsid)))
               //Any exception will do. We just need to break out of the
               //TRY statement.
               AfxThrowMemoryException();

            // Create the Excel embedded item.
            if(!pItem->CreateNewItem(clsid))
               //Any exception will do. We just need to break out of the
               //TRY statement.
               AfxThrowMemoryException();

            //Make sure the new CContainerItem is valid.
            ASSERT_VALID(pItem);

            // Launch the server to edit the item.
            pItem->DoVerb(OLEIVERB_SHOW, this);


            // As an arbitrary user interface design, this sets the
            // selection to the last item inserted.
            m_pSelection = pItem;   // set selection to last inserted item
            pDoc->UpdateAllViews(NULL);

            //Query for the dispatch pointer for the embedded object. In
            //this case, this is the Excel worksheet.
            LPDISPATCH lpDisp;
            lpDisp = pItem->GetIDispatch();

            //Add text in cell A1 of the embedded Excel sheet
            _Workbook wb;
            Worksheets wsSet;
            _Worksheet ws;
            Range range;
            _Application app;

            //set _Workbook wb to use lpDisp, the IDispatch* of the
            //actual workbook.
            wb.AttachDispatch(lpDisp);


            //Then get the worksheet's application.
            app = wb.GetApplication();

            //Then get the first worksheet in the workbook
            wsSet = wb.GetWorksheets();
            ws = wsSet.GetItem(COleVariant((short)1));

            //From there, get a Range object corresponding to cell A1.
            range = ws.GetRange(COleVariant("A1"), COleVariant("A1"));

            //Fill A1 with the string "Hello, World!"
            range.SetValue(COleVariant("Hello, World!"));

           //NOTE: If you are automating Excel 2002, the Range.SetValue method has an 
           //additional optional parameter specifying the data type.  Because the 
           //parameter is optional, existing code will still work correctly, but new 
           //code should use the new convention.  The call for Excel2002 should look 
           //like the following:

           //range.SetValue( C<?xm-insertion_mark_start author="v-thomr" time="20070326T121607-0600"?>O<?xm-insertion_mark_end?><?xm-deletion_mark author="v-thomr" time="20070326T121606-0600" data="o"?>leVariant( (long)DISP_E_PARAMNOTFOUND, VT_ERROR ), 
           //                COleVariant("Hello, World!"));
         }

           //Here, we need to do clean up if something went wrong.
           CATCH(CException, e)
           {
              if (pItem != NULL)
              {
                 ASSERT_VALID(pItem);
                 pItem->Delete();

              }
              AfxMessageBox(IDP_FAILED_TO_CREATE);
           }
           END_CATCH

           //Set the cursor back to normal so the user knows exciting stuff
           //is no longer happening.
           EndWaitCursor();
        }

					
8. Embed_ExcelView.h에 다음 줄을 추가합니다.
      #include "excel8.h"
						
참고 헤더 파일은 Excel 2000을 자동화할 경우 "excel9.h"이고, Excel 2002 이상을 자동화할 경우 "excel.h"입니다.
9. View 클래스의 OnInsertObject() 메서드를 확인합니다. 이 메서드와 방금 작성된 메서드가 매우 비슷하다는 것을 알 수 있습니다. 사실, 작성된 코드는 OnInsertObject()의 특수한 경우에 해당하므로 이를 사용하면 사용 가능한 OLE 개체 목록에서 OLE 개체를 선택하여 응용 프로그램에 삽입할 수 있습니다. Excel 워크시트를 자동화하기만 하면 되기 때문에 이러한 동작은 무시합니다. 만든 응용 프로그램에 대해 InsertObject() 내부에서 모든 코드를 제거하고 이를 EmbedAutomateExcel()에 대한 호출로 대체합니다.
10. 응용 프로그램을 컴파일하고 실행합니다.
11. Edit 메뉴에서 Insert New Object를 누릅니다.
결과: Microsoft Excel 워크시트가 View에 포함되고, 자동화를 통해 셀 A1이 "Hello, World!"로 채워집니다.



Microsoft 제품 관련 기술 전문가들과 온라인으로 정보를 교환하시려면 Microsoft 뉴스 그룹 (http://support.microsoft.com/newsgroups/default.aspx)에 참여하시기 바랍니다.