HOWTO · Csharp

C#에서 Excel 파일에 쓰기

Microsoft Office API를 사용하여 C#으로 Excel 파일에 쓸 수 있습니다.

이 페이지의 내용

C#에서 Excel 통합 문서에 데이터를 쓰려면 설치된 데스크톱 Excel을 자동화해야 하는 경우 Microsoft Office Interop을 사용하세요. Interop으로 통합 문서를 만들고 셀을 채운 다음 기본 .xlsx 파일로 저장할 수 있습니다. 프로그램을 실행하는 컴퓨터에는 Excel이 설치되어 있어야 합니다. 배포 환경에서 Excel을 사용할 수 없다면 통합 문서 파일을 직접 작성하는 스프레드시트 라이브러리를 사용하세요.

애플리케이션에 적합한 Excel 작성 방법 선택

Microsoft Office Interop은 Excel을 시작하고 COM을 통해 Excel 개체 모델과 통신합니다. Excel 자체의 동작에 의존하는 데스크톱 자동화, 예를 들어 Excel 전용 통합 문서 기능을 사용해야 할 때 선택하세요. Interop은 독립 실행형 파일 작성 라이브러리가 아닙니다. 프로젝트에 Interop 참조를 추가해도 다른 컴퓨터에 Excel이 설치되지는 않습니다.

워크시트, 수식 또는 서식이 필요 없는 단순한 표 형식 데이터라면 CSV 파일을 사용할 수 있습니다. Excel에서 CSV 텍스트를 열 수는 있지만, CSV는 Excel 통합 문서가 아니며 통합 문서 기능을 저장할 수 없습니다. 아래 예제에서는 두 가지 결과를 구분해 설명합니다.

C#에서 Microsoft Office Interop 설정

Visual Studio에서 프로젝트의 References 대화 상자를 열고 Microsoft Excel Object Library에 대한 COM 참조를 추가하세요. 라이브러리 버전은 설치된 Office 버전에 따라 달라집니다. 초기 바인딩 참조를 사용한다면 Microsoft.Office.Interop.Excel을 가져오세요. 예를 들어 using Excel = Microsoft.Office.Interop.Excel;을 사용하면 Excel 형식과 이름이 비슷한 .NET 형식을 구분할 수 있습니다.

아래 통합 문서 예제는 Excel COM ProgID를 통한 지연 바인딩을 사용하므로 소스 코드에 해당 네임스페이스가 필요하지 않습니다. 하지만 이 방법도 Excel을 자동화하며, 실행 시 Windows에 Excel이 설치되어 있어야 합니다. 컴파일 시 Excel 형식을 검사하고 IntelliSense를 사용하려면 초기 바인딩 참조를 사용하세요. 배포 환경에서 설치된 Excel 버전을 관리하고 특정 버전에 종속된 참조를 피하려면 지연 바인딩을 사용할 수 있습니다. 참조를 추가하는 것만으로 서버나 다른 컴퓨터에서 Excel을 사용할 수 있게 되는 것은 아닙니다.

통합 문서를 만들고 셀에 데이터 쓰기

이 Interop 예제는 Excel을 시작하고 통합 문서를 추가한 뒤, 머리글과 데이터 행 두 개를 작성하고 시스템 임시 디렉터리에 기본 .xlsx 파일로 저장합니다. 형식 값 51은 Excel의 xlOpenXMLWorkbook 파일 형식입니다. GUID를 사용해 실행할 때마다 출력 파일 이름을 고유하게 만들므로 숨겨진 Excel 인스턴스가 덮어쓰기 확인을 기다리지 않습니다. 이 코드는 데스크톱 Excel이 설치된 Windows 환경을 대상으로 하며, 실행 결과는 제시하지 않습니다.
이 섹션의 코드와 표시되는 레이블 또는 출력은 영어로 유지됩니다.

using System;
using System.IO;
using System.Runtime.InteropServices;

class Program
{
    static void Main()
    {
        if (Environment.OSVersion.Platform != PlatformID.Win32NT)
        {
            Console.WriteLine("This example requires Windows with Excel installed.");
            return;
        }

        object excelApp = null;
        object workbooks = null;
        object workbook = null;
        object worksheets = null;
        object worksheet = null;
        object cells = null;

        try
        {
            Type excelType = Type.GetTypeFromProgID("Excel.Application");
            if (excelType == null)
            {
                Console.WriteLine("Excel is not registered on this computer.");
                return;
            }

            dynamic app = Activator.CreateInstance(excelType);
            excelApp = app;
            app.Visible = false;
            workbooks = app.Workbooks;
            dynamic books = workbooks;
            workbook = books.Add();
            dynamic book = workbook;
            worksheets = book.Worksheets;
            dynamic sheets = worksheets;
            worksheet = sheets[1];
            dynamic sheet = worksheet;

            cells = sheet.Range["A1:B3"];
            dynamic dataRange = cells;
            object[,] values =
            {
                { "Name", "Age" },
                { "Ava", 28 },
                { "Liam", 31 }
            };
            dataRange.Value2 = values;

            string fileName = "example-" + Guid.NewGuid().ToString("N") + ".xlsx";
            string path = Path.Combine(Path.GetTempPath(), fileName);
            book.SaveAs(path, 51);
            Console.WriteLine("Saved " + Path.GetFileName(path));
        }
        catch (Exception ex)
        {
            Console.WriteLine("Excel operation failed: " + ex.Message);
        }
        finally
        {
            CloseWorkbook(workbook);
            ReleaseComObject(cells);
            ReleaseComObject(worksheet);
            ReleaseComObject(worksheets);
            ReleaseComObject(workbook);
            ReleaseComObject(workbooks);
            QuitExcel(excelApp);
            ReleaseComObject(excelApp);
        }
    }

    static void CloseWorkbook(object value)
    {
        if (value == null) return;
        try { ((dynamic)value).Close(false); }
        catch { }
    }

    static void QuitExcel(object value)
    {
        if (value == null) return;
        try { ((dynamic)value).Quit(); }
        catch { }
    }

    static void ReleaseComObject(object value)
    {
        if (value == null) return;
        try
        {
            if (Marshal.IsComObject(value)) Marshal.FinalReleaseComObject(value);
        }
        catch { }
    }
}

단순한 표 형식 데이터라면 별도의 CSV 예제를 사용해 Excel에서 열 수 있는 쉼표로 구분된 텍스트를 작성할 수 있습니다. 이 방법은 통합 문서를 만들지 않으며 여러 시트, 수식 또는 서식을 지원하지 않습니다. 예제 값에는 CSV 따옴표 처리가 필요하지 않습니다. 임의의 텍스트를 쓸 때는 쉼표, 따옴표 또는 줄 바꿈이 포함된 필드를 따옴표로 감싸고, 필드 안의 따옴표는 두 번 써서 이스케이프하세요.

이 예제를 실행하세요:

using System;
using System.IO;

class Program
{
    static void Main()
    {
        string path = "example.csv";
        string contents = "Name,Age\nJohn Doe,30\n";
        File.WriteAllText(path, contents);
        Console.WriteLine("Wrote " + path);
    }
}
Wrote example.csv

기존 Excel 파일에 쓰기

전체 경로로 통합 문서를 열고, 선택한 범위를 COM 참조로 유지한 다음 정리 단계에서 해제하세요. Save는 열어 둔 파일을 그 자리에서 업데이트합니다. 새 경로에 저장하거나 사본을 만들려면 SaveAs를 사용하세요. 예제 경로를 수정하려는 통합 문서의 경로로 바꾸세요. 이 Windows 데스크톱 Excel 예제는 실행 결과를 제시하지 않습니다.
이 섹션의 코드와 표시되는 레이블 또는 출력은 영어로 유지됩니다.

using System;
using System.IO;
using System.Runtime.InteropServices;

class Program
{
    static void Main()
    {
        if (Environment.OSVersion.Platform != PlatformID.Win32NT)
        {
            Console.WriteLine("This example requires Windows with Excel installed.");
            return;
        }

        object excelApp = null;
        object workbooks = null;
        object workbook = null;
        object worksheets = null;
        object worksheet = null;
        object cells = null;
        string path = Path.Combine(
            Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments),
            "report.xlsx");

        try
        {
            if (!File.Exists(path))
                throw new FileNotFoundException("Workbook not found; update the sample path.", path);

            Type excelType = Type.GetTypeFromProgID("Excel.Application");
            if (excelType == null)
                throw new InvalidOperationException("Excel is not registered on this computer.");

            dynamic app = Activator.CreateInstance(excelType);
            excelApp = app;
            app.Visible = false;
            workbooks = app.Workbooks;
            dynamic books = workbooks;
            workbook = books.Open(path);
            dynamic book = workbook;
            worksheets = book.Worksheets;
            dynamic sheets = worksheets;
            worksheet = sheets[1];
            dynamic sheet = worksheet;
            cells = sheet.Range["B2:C2"];
            dynamic selectedCells = cells;
            selectedCells.Value2 = new object[,] { { "Reviewed", DateTime.Today.ToString("yyyy-MM-dd") } };
            book.Save();
            Console.WriteLine("Updated " + Path.GetFileName(path));
        }
        catch (Exception ex)
        {
            Console.WriteLine("Excel operation failed: " + ex.Message);
        }
        finally
        {
            CloseWorkbook(workbook);
            ReleaseComObject(cells);
            ReleaseComObject(worksheet);
            ReleaseComObject(worksheets);
            ReleaseComObject(workbook);
            ReleaseComObject(workbooks);
            QuitExcel(excelApp);
            ReleaseComObject(excelApp);
        }
    }

    static void CloseWorkbook(object value)
    {
        if (value == null) return;
        try { ((dynamic)value).Close(false); }
        catch { }
    }

    static void QuitExcel(object value)
    {
        if (value == null) return;
        try { ((dynamic)value).Quit(); }
        catch { }
    }

    static void ReleaseComObject(object value)
    {
        if (value == null) return;
        try
        {
            if (Marshal.IsComObject(value)) Marshal.FinalReleaseComObject(value);
        }
        catch { }
    }
}

원본이 CSV라면 파일 입출력으로 행을 다시 작성하세요. CSV에는 워크시트나 셀 개체 모델이 없습니다.

Excel 닫기 및 오류 처리

경로를 사용할 수 없거나 대상 위치에 쓸 수 없으면 파일 작업이 실패할 수 있습니다. Interop 작업도 Excel 시작, 통합 문서 열기, 셀 쓰기 또는 저장 중에 실패할 수 있으며, 통합 문서가 사용 중인 경우에도 오류가 발생할 수 있습니다. 애플리케이션에서 유용한 메시지를 표시하거나 기록할 수 있는 지점에서 오류를 처리하세요. 통합 문서 닫기, Quit, COM 참조 해제는 finally에 넣으세요. 오류를 잡는 것만으로 Excel 리소스가 정리되지는 않습니다. 예제에서는 닫기 작업 하나가 실패해도 이후 정리 작업을 건너뛰지 않도록 각 정리 작업을 개별적으로 보호합니다.

Excel 애플리케이션의 수명은 필요한 작업 시간으로 제한하고, 추적되지 않는 Range 개체 같은 불필요한 COM 참조를 보유하지 마세요. 예제를 적용할 때는 임시 출력 경로를 원하는 위치로 바꾸세요. 서식을 지정하려면 값을 쓴 뒤 해당 워크시트 범위의 속성을 설정하세요. CSV 출력은 서식을 보존할 수 없습니다. 애플리케이션에서 CSV 예제를 사용한다면 파일 입출력 오류 처리도 추가해야 합니다.