윈도우 프로그램은 특히 엑셀 파일을 읽을 일이 자주 있습니다. C#으로 엑셀 파일에서 데이터를 읽어오는 방법에 대해 알아보겠습니다.
저번 포스트에는 C#으로 엑셀 파일을 읽어들이는 법에 대해 알아보았습니다.
이번에는
C#으로 엑셀 파일을 저장하는 방법에 대해 알아보겠습니다.
Excel 프로그램이 설치되어 있어야 하며, 프로그램을 사용할 컴퓨터에도 설치되어 있어야 합니다.
※ 이 포스트는 과거 티스토리 블로그의 글을 개선한 글입니다.
우선 Reference를 추가해주어야 합니다.
프로젝트 참조추가 -> COM -> Microsoft Excel 16.0 Object Library
여기서 숫자(16.0)는 다를 수 있습니다.
편의를 위해 Excel 관련 using문을 추가해줍니다.
1
2
using System.Runtime.InteropServices;
using Excel = Microsoft.Office.Interop.Excel;
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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
private static bool WriteExcelData(string path, string[][] targetData)
{
uint excelProcessId = 0;
Excel.Application excelApp = null;
Excel.Workbook wb = null;
Excel.Worksheet ws = null;
try
{
// Execute Excel application
excelApp = new Excel.Application();
GetWindowThreadProcessId(new IntPtr(excelApp.Hwnd), out excelProcessId);
// 엑셀파일 열기 or 새로 만들기
bool isFileExist = File.Exists(path);
wb = isFileExist ? excelApp.Workbooks.Open(path, ReadOnly: false, Editable: true) : excelApp.Workbooks.Add(Missing.Value);
ws = wb.Worksheets.get_Item(1) as Excel.Worksheet;
// Worksheet 이름 설정하기
// ws.Name = targetWorksheetName ;
int row = targetData.GetLength(0);
int column = targetData[0].Length;
object[,] data = new object[row, column];
for (int r = 0; r < row; r++)
{
for (int c = 0; c < column; c++)
{
data[r, c] = targetData[r][c];
}
}
// row, column 번호로 Cell 접근
// Excel.Range rng = ws.Range[ws.Cells[1, 1], ws.Cells[row, column]];
Excel.Range rng = ws.get_Range("A1", Missing.Value);
rng = rng.get_Resize(row, column);
// 저장하는 여러 방법 중 두가지
// rng.Value = data;
rng.set_Value(Missing.Value, data);
if (isFileExist)
{
wb.Save(); // 덮어쓰기
}
else
{
wb.SaveCopyAs(path); // 새 파일 만들기
}
wb.Close(false);
excelApp.Quit();
}
catch (Exception e)
{
if (wb != null)
{
wb.Close(SaveChanges: false);
}
if (excelApp != null)
{
excelApp.Quit();
}
return false;
}
finally
{
ReleaseExcelObject(ws);
ReleaseExcelObject(wb);
ReleaseExcelObject(excelApp);
if (excelApp != null && excelProcessId > 0)
{
Process.GetProcessById((int)excelProcessId).Kill();
}
}
return true;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
private static void ReleaseExcelObject(object obj)
{
try
{
if (obj != null)
{
Marshal.ReleaseComObject(obj);
obj = null;
}
}
catch (Exception)
{
obj = null;
throw;
}
finally
{
GC.Collect();
}
}
1
2
[DllImport("user32.dll", SetLastError = true)]
static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
파일 쓰기의 경우 2가지 경우가 있습니다.
두가지 방법 모두 확인해보겠습니다.
주석으로 간략히 설명하였지만, 글로써 자세히 설명합니다.
Excel은 index가 1부터 시작합니다.(1-based)
Missing.Value = 의미 없는 값
bool WriteExcelData(string path, string[][] targetData)
string path
: Excel 파일 경로string[][] targetData
: 저장할 데이터path
가 존재할 경우 Workbooks의 Open(열기), 없을 경우 Add(새로 만들기)void ReleaseExcelObject(object obj)
: 사용한 Excel Object를 Release(free 개념) 해줍니다.GetWindowThreadProcessId(new IntPtr(excelApp.Hwnd), out excelProcessId)
예시로 C# 콘솔 프로젝트를 GitHub에 업로드 해놓았으니, 보시면서 활용하시면 좋을 것 같습니다.