COM : Component Object Model
마이크로소프트 프로그램들 간에 상호작용이 가능하게 해주는 기능입니다.
C#과 Excel을 연결해서 사용해 봅시다. 우선 윈폼을 만들어 진행해 봅니다. (UI 진행은 대충 생략했습니당!)
button1 : 열 추가
button2 : 엑셀에 저장
dataGridView1 : 데이터 관리
참조에서 마우스 오른쪽 클릭을 해줍니다.
참조 추가를 눌러줍니다.
참조 관리자에서 COM 메뉴를 클릭하고 Microsoft Excel 을 찾아서 참조합니다.
(설치되어 있는 버전에 따라 16.0이 아닐 수도 있지만 사용 가능해요!)
오른쪽 참조에 Microsoft.Office.Interop.Excel 가 생겼습니다.
using Microsoft.Office.Interop.Excel;
이 후 Microsoft.Office.Interop.Excel.Application 등을 사용할 수 있습니다.
이름이 너무 길어 불편하기 때문에
using Excel = Microsoft.Office.Interop.Excel;
라고 별칭을 주어 Excel로 해당 이름을 대체해줍니다.
코드를 보기전에 짤막하게 설명을 해보겠습니다.
workbook = 하나의 엑셀 파일
worksheet = 엑셀의 시트 (workbook의 worksheet) , 인덱스는 1부터 시작됩니다.
초록 라인 역시 1, 1 로 시작합니다.
이제 간단히 동작을 봅시다. 전체 코드는 맨 마지막에 있습니다.
워크북 생성 후 워크시트에 접근하여 사용할 수 있습니다.
엑셀을 보여지게 하고, AA 작성을 한 결과입니다.
나머지는 코드를 참고하시면 되겠습니다.
인터넷을 참고하니 ReleaseExcelObject 로 엑셀 연결에 사용된 메모리를 관리하는군요. 긁어왔습니다. ㅎㅎ
한 가지 주의 할 점은
dataGridView는 [column, row] 순서로 읽고
excel은 [row, column] 순으로 읽습니다. 게다가 인덱스가 1부터 시작되기에 row + 1, column + 1로 해주게 됩니다.
![]() |
![]() |
using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using Excel = Microsoft.Office.Interop.Excel;
namespace ExcelForm
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
//그리드뷰 컬럼을 증가시킵니다.
private void button1_Click(object sender, EventArgs e)
{
int index = dataGridView1.ColumnCount;
dataGridView1.ColumnCount++;
dataGridView1.Columns[index].HeaderText = (index + 1).ToString();
}
//엑셀 파일에 저장합니다.
private void button2_Click(object sender, EventArgs e)
{
Excel.Application app = new Excel.Application();
//app.Visible = true; //엑셀을 보여줍니다.
Excel.Workbook workbook = app.Workbooks.Add(); //엑셀 창 환경을 가집니다.
Excel.Worksheet worksheet = workbook.Worksheets[1]; // Sheet1 환경을 가집니다.
//Excel.Worksheet worksheet = workbook.Worksheets.get_Item(1);
//엑셀은 모든 인덱스가 0이 아닌 "1" 부터 시작합니다 주의하세요!
for (int row = 0; row < dataGridView1.RowCount; ++row)
{
for (int column = 0; column < dataGridView1.ColumnCount; ++column)
{
if (dataGridView1[column, row].Value == null)
{
continue;
}
worksheet.Cells[row + 1, column + 1] = dataGridView1[column, row].Value.ToString();
}
}
try
{
string path = Path.Combine(Environment.CurrentDirectory, "Test.xlsx");
worksheet.SaveAs(path); //파일 덮어쓰기를 선택하지 않으면 오류가 납니다.
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
finally
{
workbook.Close();
app.Quit();
ReleaseExcelObject(worksheet);
ReleaseExcelObject(workbook);
ReleaseExcelObject(app);
}
}
//엑셀 파일을 읽어옵니다.
private void button3_Click(object sender, EventArgs e)
{
Excel.Application app = new Excel.Application();
string path = Path.Combine(Environment.CurrentDirectory, "Test.xlsx");
Excel.Workbook workbook = app.Workbooks.Open(path);
Excel.Worksheet worksheet = workbook.Worksheets[1];
Excel.Range range = worksheet.UsedRange;
object[,] data = range.Value;
int rowCount = data.GetLength(0);
int columnCount = data.GetLength(1);
//엑셀 크기보다 dataGirdView가 작다면 넓혀준다.
if (dataGridView1.RowCount < rowCount)
{
dataGridView1.RowCount = rowCount;
}
if (dataGridView1.ColumnCount < columnCount)
{
dataGridView1.ColumnCount = columnCount;
}
for (int row = 0; row < data.GetLength(0); ++row)
{
for (int column = 0; column < data.GetLength(1); ++column)
{
dataGridView1[column, row].Value = data[row + 1, column + 1];
}
}
workbook.Close();
app.Quit();
ReleaseExcelObject(worksheet);
ReleaseExcelObject(workbook);
ReleaseExcelObject(app);
}
private void ReleaseExcelObject(object obj)
{
try
{
if (obj != null)
{
Marshal.ReleaseComObject(obj);
obj = null;
}
}
catch (Exception ex)
{
obj = null;
throw ex;
}
finally
{
GC.Collect();
}
}
}
}