c# excel 파일 읽기
들어가기 전에,
c#을 하면서, 참.. 언어만 공부해서 되는게 아니고, 설정등을 공부해야하는게 참 고달프다.
참고로 저는 c++만 좀 하다가, 이제 C#에 인문하는 햇병아리입니다.
목표 :
- C#에서 임의의 Excel파일을 열어서 모든 excel의 cells정보를 변수로 저장한다.
- 저장된 변수를 출력한다
이후 추가 목표 :
- 저장된 변수를 excel의 cells에 쓰고 저장한다.
- Excel파일 뿐만아니라, CVS파일도 동일하게 읽고 쓸 수 있도록 한다.
- 이 것을 DLL로 만들어 Excel format을 읽고 쓸 수 있도록 하는 DLL를 생성한다.
사전작업
1. Microsoft.Oiffice.Interop.Excel 라이브러리 추가
- 추가방법 : [참조] > [마우스 우클릭]::[참조추가] > [COM]::[클릭] > [Microsoft.Oiffice.Interop.Excel]::[클릭]::[확인]
2. System.Windows.Forms 추가
Excel Data가 어떻게 되어 있던간에, 모든 Data를 일반화하여 2차원 배열로 들고 있고 싶다.
그래서 상황에 따라, 해당 Data를 원하는 자료형으로 Convert해서 지지고 볶고 하고 싶다.
단순히 class library에 해당 class와 method를 생성해서, main에서 불러주는 형태로 사용하고 싶은데, 제약상황이 많다.
왜냐하면, class library를 생성한뒤, [System.Windows.Forms]를 추가하여 사용할 수 없기 때문이다.
이럴 경우 Form을 생성하면 [System.Windows.Forms] 을 사용 할 수 있다.
[System.Windows.Forms] 을 사용하는 이유.
[OpenFileDialog] class를 사용할 수 있다.
[OpenFileDialog]는 Excel파일을 쉽게 읽고 쓸 수 있게 하는 method를 갖고 있다.
3. System.IO 추가
[System.IO]를 사용하는 이유.
[System.IO]하위에 Path.GetExtension({OpenFileDialog.FileName})함수로 읽고자 하는 파일의 확장자를 쉽게 알수 있다.
4. UserClass 생성하고 Excel 읽어오는 Method 만들기
프로젝트에서 C# 클래스 라이브러리로 추가 한뒤, 아래와 같이 class와 method를 작성.
public class UserClass {
//생성자 인스턴스값 초기화
public UserClass {
OpenFileDialog openFileDialog = null;
object[,] data = null;
}
//[Systehttp://m.Windows.Forms]에 포함된 OpenFileDialog형 인스턴스 추가
OpenFileDialog openFileDialog;
//ExcelData는 2차원 배열이기 때문에, Object타입 인스턴스 추가
object[,] data;
//UserClass에서 사용하는 ExcelOpen 함수 정의
public int ExcelOpen(ref ALSDATA_FORMAT input) {
//[Microsoft.Oiffice.Interop.Excel]라이브러리를 통해 Excel APP, WorkBook, Sheet단위로 접근할 변수 생성
Microsoft.Office.Interop.Excel.Application app = null;
Microsoft.Office.Interop.Excel.Workbook workbook = null;
Microsoft.Office.Interop.Excel.Worksheet worksheet = null;
//Exception 발생가능성 있는부분 try, catch, finally 구분 생성.
try {
//app, workbook, worksheet는 아래와 같이 사용된다.
/*
* app : Excel Application을 활성화 한다.
* app.Visible : false면 화면 안띄우고, true면 화면 띄운다.
* workbook : app의 workbook 오픈
* worksheet : workbook의 첫번째 쉬트 오픈
* range : Excel의 Workbook의 첫번째 Sheet에 사용된 Cells을 읽어와서 range변수에 저장.
* object는 2차원 Array이므로 range와 딱 맞음.
* object를 UserClass의 object형 data에 Setting해준다.
*/
app = new Microsoft.Office.Interop.Excel.Application();
app.Visible = false;
workbook = app.Workbooks.Open(openFileDialog.FileName);
worksheet = workbook.Worksheets.get_Item(1) as Microsoft.Office.Interop.Excel.Worksheet;
Microsoft.Office.Interop.Excel.Range range = worksheet.UsedRange;
object[,] data = range.Value2;
input.data = data;
}
catch (Exception ex) {
//예외발생시 메시지박스 예외 출력.
MessageBox.Show(ex.ToString());
//Main에서 사용시 오류 처리를 위해 -1 return.
//이 함수가 void일 경우, throw처리 해도 된다.
return -1;
}
finally {
//try끝나고, finally 처리.
/*
* 열린, workbook 닫아주고,
* app 종료하고
*
* 메모리 해제는 선언의 역순.
* worksheet해제, workbook해제, app해제
*/
workbook.Close(true);
app.Quit();
ReleaseExcelObject(worksheet);
ReleaseExcelObject(workbook);
ReleaseExcelObject(app);
}
}//ExcelOpen
//Excel 변수 메모리 해제
private void ReleaseExcelObject(object obj) {
try {
if (obj != null) {
Marshal.ReleaseComObject(obj);
obj = null;
}
}
catch (Exception ex) {
obj = null;
throw ex;
}
finally {
GC.Collect();
}
}//ReleaseExcelObject
}//UserClass
위 class에서 사용되는 Method는 인터넷에 많이 나와있는 방법들을 참고했다.
위의 UserClass의 namespace를 UserLib라고 하면 아래와 같은구성이 된다.
위와 같이 method를 생성해두면, 실제로 main에서는 아래와 같이 사용할 수 있다.
5. UserClass가 포함된 UserDLL namespace
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using Microsoft.Office.Interop.Excel;
using System.Windows.Forms;
using System.IO;
using System.Text;
namespace UserDLL {
public class UserClass {
//생략.
}
}
6. Main에서 UserClass의 Method 사용하기
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
//MS Office COM
using Microsoft.Office.Interop.Excel;
using ALSLib;
using System.IO;
using System.Data.Common;
using static System.Net.Mime.MediaTypeNames;
namespace UserDLL {
public partial class UserAPP : Form {
UserClass user = new UserClass();
public UserAPP() {
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e) {
int iRet = 0;
try {
//이런식으로 사용하면 된다.
iRet = user.ExcelOpen(ref user);
//아직 미구현, 앞으로 구현할 method 형태
//iRet = format.ExcelSave(ref format);
} catch {
throw;
}
}//button1
}//Form
}//namespace
생각 보다 쉽다.
Form에서 우리가 만든 UserClass 객체생성.
버튼하나 만들어서, 그버튼에서 UserClass의 Method인 ExcelOpen() 호출
끝.
이제 마지막으로 하나 남았다.
7. 저장된 변수 Main에서 출력하기.
namespace UserDLL {
public partial class UserAPP : Form {
UserClass user = new UserClass();
public UserAPP() {
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e) {
int iRet = 0;
try {
//이런식으로 사용하면 된다.
iRet = user.ExcelOpen(ref user);
//데이터는 user.data에 저장되어 있으며 2차원 Array의 Ojbect이다.
//이중 For문으로 행과 열에 접근해서 출력해보자.
//Excel값의 Index가 1부터 Index크기까지 접근가능하다.
for (int r = 1; r <= user.data.GetLength(0); r++) {
for (int c = 1; c <= user.data.GetLength(1); c++) {
Console.WriteLine("[{0},{1}] = [{2}]", r, c, user.data[r, c]);
}
}
//아직 미구현, 앞으로 구현할 method 형태
//iRet = format.ExcelSave(ref format);
}
catch {
throw;
}
}//button1
}//Form
}//namespace
저기 이중 for문의 경우에는 따로 user.data만 매계변수로 받아 출력하도록 만들면 좋을것 같다.
다음에는 ExcelSave를 구현해보고, DLL로 만들어보자.