Notice
Recent Posts
Recent Comments
Link
«   2024/11   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
Archives
Today
Total
관리 메뉴

nomad-programmer

[Programming/C#] COM (Component Object Model) 본문

Programming/C#

[Programming/C#] COM (Component Object Model)

scii 2020. 9. 27. 00:41

COM 이란?

COM은 Component Object Model의 약자로, 마이크로소프트의 소프트웨어 컴포넌트 규격을 말한다. OLE, ActiveX, COM+와 같은 파생 규격들이 모두 COM을 바탕으로 만들어졌다. 
마이크로소프트에서 출시되는 대부분의 제품이 COM을 지원한다.

COM은 부품 역할을 하는 소프트웨어이다. COM 컴포넌트는 그래픽 프로그래밍에 서툰 프로그래머가 화려한 차트 기능을 어플리케이션에 넣을 수 있도록 해주고, 엑셀 문서의 파일 구조를 몰라도 엑셀 문서를 읽거나 쓸 수 있도록 해준다.

C#을 비롯한 .NET 언어들은 RCW(Runtime Callable Wrapper)를 통해 COM 컴포넌트를 사용할 수 있다.
RCW는 .NET 프로엠워크가 제공하는 Type Library Importer(tlbimp.exe)를 이용해서 만들 수 있는데, 비주얼 스튜디오를 이용해서 COM 객체를 프로젝트 참조에 추가하면 IDE가 자동으로 tlbimp.exe를 호출하여 RCW를 만들어준다. 

RCW는 COM에 대한 proxy 역할을 함으로써 C#코드에서 .NET 클래스 라이브를 사용하듯 COM API를 사용할 수 있게 해준다.

C#과 COM

C# 4.0 이전에는 COM 친화적인 언어였던 비주얼 베이직은 COM과 잘 어울렸지만, C#은 RCW가 있어도 여전히 COM과 친화적이지 않았다. 그 원인은 다음의 두가지이다.

  1. COM은 메소드가 결과를 반환할 때 실제 형식이 아닌 object 형식으로 반환한다. 이 때문에 C# 코드에서는 이 결과를 실제 형식으로 변환을 해줘야 하는 번거로움이 있었다.
  2. COM은 오버로딩을 지원하지 않는다. 대신 메소드의 선택적 매개 변수와 기본값 매개 변수를 지원한다. C#은 4.0 버전으로 업그레이드되기 전까지는 선택적 매개 변수와 기본값 매개 변수를 지원하지 못했다. 이 때문에 C# 코드에서 COM API 하나를 호출하려면 사용하지도 않을 매개 변수를 수없이 입력해줘야 하는 번거로움이 있었다.

C# 4.0 버전에 이르러서야 dynamic 형식의 도임을 통해 1번 문제를 해결하고, 메소드의 선택적 매개 변수와 기본값 매개 변수 도입을 통해 2번 문제를 해소했다. 비로소 C#도 VB처럼 COM 친화적인 언어가 된 것이다.

마이크로소프트는 워드를 비롯해 파워포인트, 엑셀 등 오피스 제품들의 기능을 코드에서 이용할 수 있도록 이 소프트웨어들을 COM 컴포넌트로 구성해 놓았다.

// C# 3.0 이하

public static void OldWay(string[,] data, string savePath)
{
    Excel.Application excelApp = new Excel.Application();

    excelApp.Workbooks.Add(Type.Missing);

    Excel.Worksheet workSheet = (Excel.Worksheet)excelApp.ActiveSheet;

    for(int i=0; i< data.GetLength(0); i++)
    {
        ((Excel.Range)workSheet.Cells[i + 1, 1]).Value2 = data[i, 0];
        ((Excel.Range)workSheet.Cells[i + 1, 2]).Value2 = data[i, 1];
    }

    workSheet.SaveAs(
        savePath + "\\test-book_old.xlsx",
        Type.Missing,
        Type.Missing,
        Type.Missing,
        Type.Missing,
        Type.Missing,
        Type.Missing,
        Type.Missing,
        Type.Missing);

    excelApp.Quit();
}
// C# 4.0 이상

public static void NewWay(string[,] data, string savePath)
{
    Excel.Application excelApp = new Excel.Application();

    excelApp.Workbooks.Add();

    Excel._Worksheet workSheet = excelApp.ActiveSheet;

    for(int i=0; i<data.GetLength(0); i++)
    {
        workSheet.Cells[1 + 1, 1] = data[i, 0];
        workSheet.Cells[1 + 1, 2] = data[i, 1];
    }

    workSheet.SaveAs(savePath + "\\test-book-dynamic.xlsx");
    excelApp.Quit();
}

C# 4.0 버전 이후로 수많은 형식 변환과 의미 없는 매개 변수 입력이 사라졌다. 선택적 매개 변수와 dynamic 형식은 비주얼 스튜디오가 RCW를 만들 때 사용했다.

Excel COM 사용 예제

1. 비주얼 스튜디오에서 새 프로젝트를 생성합니다. "콘솔 앱 (.NET Framework)" 템플릿 선택. 프로젝트 이름은 알아서 정하면 된다.

2. 솔루션 탐색기에서 Program.cs 파일의 이름을 원하는 이름으로 변경한다.

3. 솔루션 탐색기에서 "References (참조)" 항목 위에 마우스 오른쪽 버튼을 클릭하여 [Add Reference... (참조 추가)] 항목을 선택한다.

References에서 마우스 우측 클릭 후 참조 추가를 클릭

4. 아래와 같은 창이 나타나면, 창의 왼편에서 [COM] -> [Type Libraries] 항목을 선택한다. 그리고 구성 요소 목록에서 "Microsoft Excel 16.0 Object Library" 를 선택한 후 <확인> 버튼을 클릭한다.

Excel COM 추가

5. 작업이 성공적으로 진행되었다면 아래와 같이 References 항목에 Microsoft.Office.Core 어셈블리와 Microsoft.Office.Interop.Excel 어셈블리가 추가된 것을 확인할 수 있다.

어셈블리가 추가된 모습

Excel에 데이터를 입력한 후 저장하는 예제

using System;
using Excel = Microsoft.Office.Interop.Excel;

namespace COMInterop
{
    class MainApp
    {
        public static void OldWay(string[,] data, string savePath)
        {
            Excel.Application excelApp = new Excel.Application();

            excelApp.Workbooks.Add(Type.Missing);

            Excel.Worksheet workSheet = (Excel.Worksheet)excelApp.ActiveSheet;

            for(int i=0; i<data.GetLength(0); i++)
            {
                ((Excel.Range)workSheet.Cells[i + 1, 1]).Value2 = data[i, 0];
                ((Excel.Range)workSheet.Cells[i + 1, 2]).Value2 = data[i, 1];
            }

            workSheet.SaveAs(
                savePath + "\\test-book-old.xlsx",
                Type.Missing,
                Type.Missing,
                Type.Missing,
                Type.Missing,
                Type.Missing,
                Type.Missing,
                Type.Missing,
                Type.Missing);

            excelApp.Quit();
        }

        public static void NewWay(string[,] data, string savePath)
        {
            Excel.Application excelApp = new Excel.Application();

            excelApp.Workbooks.Add();

            Excel._Worksheet workSheet = excelApp.ActiveSheet;

            for(int i=0; i<data.GetLength(0); i++)
            {
                workSheet.Cells[i + 1, 1] = data[i, 0];
                workSheet.Cells[i + 1, 2] = data[i, 1];
            }

            workSheet.SaveAs(savePath + "\\test-book-dynamic.xlsx");

            excelApp.Quit();
        }

        static void Main(string[] args)
        {
            string savePath = System.IO.Directory.GetCurrentDirectory();
            string[,] array = new string[,]
            {
                {"자료구조와 알고리즘", "2020" },
                {"윈도우즈 프로그래밍", "2020" },
                {"리눅스 프로그래밍", "2020" },
                {"네트워크 프로그래밍", "2020" },
                {"동시성 프로그래밍", "2020" }
            };

            Console.WriteLine("creating excel document in old way...");
            OldWay(array, savePath);

            Console.WriteLine("creating excel document in new way...");
            NewWay(array, savePath);
        }
    }
}


/* 결과

creating excel document in old way...
creating excel document in new way...

프로그램을 실행한 폴더를 보면 
test-old.xlsx, test-new-dynamic.xlsx 파일이 생긴것을 확인할 수 있다.

*/

데이터가 입력된 것을 확인할 수 있다.

Comments