커스텀 2부 - 커스텀 액션으로 액셀 매크로 만들기.
페이지 정보
본문
안녕하세요. 엔지엠소프트웨어입니다. [ 이전 글 ]에서 커스텀 모듈을 만드는 방법과 엑셀을 제어하는 샘플 코드에 대해 알아봤습니다. 그리고, 엔지엠 에디터에서 어떻게 사용되는지도 알아봤는데요. 혹시라도 이전 내용을 안보신 분들은 한번 읽어보세요. 그래야 이 내용을 이해할 수 있습니다. Visual Studio를 실행한 후 프로젝트를 불러오세요. 아래는 ExcelModel.cs의 전체 코드입니다.
ExcelModel.cs
using System;
using System.Reflection;
using System.Windows.Forms;
using Excel = Microsoft.Office.Interop.Excel;
namespace CustomExcelExampleModule
{
public class ExcelModel : NGM.Models.Interface.BaseCustomToolModel
{
public override string DisplayCategory => "엑셀 예제";
public override string DisplayName => "테스트 1";
public override void Execute()
{
Excel.Application oXL;
Excel._Workbook oWB;
Excel._Worksheet oSheet;
Excel.Range oRng;
try
{
//Excel을 시작하고 Application 개체를 가져옵니다.
oXL = new Excel.Application();
oXL.Visible = true;
//새 통합 문서를 받으십시오.
oWB = (Excel._Workbook)(oXL.Workbooks.Add(Missing.Value));
oSheet = (Excel._Worksheet)oWB.ActiveSheet;
//셀 단위로 표 머리글을 추가합니다.
oSheet.Cells[1, 1] = "First Name";
oSheet.Cells[1, 2] = "Last Name";
oSheet.Cells[1, 3] = "Full Name";
oSheet.Cells[1, 4] = "Salary";
//A1 : D1 형식을 굵게, 세로 정렬 = 가운데로 지정합니다.
oSheet.get_Range("A1", "D1").Font.Bold = true;
oSheet.get_Range("A1", "D1").VerticalAlignment =
Excel.XlVAlign.xlVAlignCenter;
//한 번에 여러 값에 대한 배열을 만듭니다.
string[,] saNames = new string[5, 2];
saNames[0, 0] = "John";
saNames[0, 1] = "Smith";
saNames[1, 0] = "Tom";
saNames[1, 1] = "Brown";
saNames[2, 0] = "Sue";
saNames[2, 1] = "Thomas";
saNames[3, 0] = "Jane";
saNames[3, 1] = "Jones";
saNames[4, 0] = "Adam";
saNames[4, 1] = "Johnson";
//A2 : B6을 값 배열 (이름 및 성)로 채 웁니다.
oSheet.get_Range("A2", "B6").Value2 = saNames;
//C2 : C6을 상대 공식 (= A2 & ""& B2)으로 채 웁니다.
oRng = oSheet.get_Range("C2", "C6");
oRng.Formula = "=A2 & \" \" & B2";
//D2 : D6을 수식 (= RAND () * 100000)으로 채우고 형식을 적용합니다.
oRng = oSheet.get_Range("D2", "D6");
oRng.Formula = "=RAND()*100000";
oRng.NumberFormat = "$0.00";
//자동 맞춤 열 A : D.
oRng = oSheet.get_Range("A1", "D1");
oRng.EntireColumn.AutoFit();
//분기 별 판매 데이터에 대해 가변 개수의 열을 조작합니다.
DisplayQuarterlySales(oSheet);
//Excel이 표시되는지 확인하고 사용자가 Microsoft Excel의 수명을 제어 할 수 있도록합니다.
oXL.Visible = true;
oXL.UserControl = true;
}
catch (Exception theException)
{
String errorMessage;
errorMessage = "Error: ";
errorMessage = String.Concat(errorMessage, theException.Message);
errorMessage = String.Concat(errorMessage, " Line: ");
errorMessage = String.Concat(errorMessage, theException.Source);
MessageBox.Show(errorMessage, "Error");
}
}
private void DisplayQuarterlySales(Excel._Worksheet oWS)
{
Excel._Workbook oWB;
Excel.Series oSeries;
Excel.Range oResizeRange;
Excel._Chart oChart;
String sMsg;
int iNumQtrs;
//데이터를 표시 할 분기 수를 결정합니다.
for (iNumQtrs = 4; iNumQtrs >= 2; iNumQtrs--)
{
sMsg = "Enter sales data for ";
sMsg = String.Concat(sMsg, iNumQtrs);
sMsg = String.Concat(sMsg, " quarter(s)?");
DialogResult iRet = MessageBox.Show(sMsg, "Quarterly Sales?",
MessageBoxButtons.YesNo);
if (iRet == DialogResult.Yes)
break;
}
sMsg = "Displaying data for ";
sMsg = String.Concat(sMsg, iNumQtrs);
sMsg = String.Concat(sMsg, " quarter(s).");
MessageBox.Show(sMsg, "Quarterly Sales");
//E1부터 선택한 열 수에 대한 헤더를 채 웁니다.
oResizeRange = oWS.get_Range("E1", "E1").get_Resize(Missing.Value, iNumQtrs);
oResizeRange.Formula = "=\"Q\" & COLUMN()-4 & CHAR(10) & \"Sales\"";
//머리글의 방향 및 WrapText 속성을 변경합니다.
oResizeRange.Orientation = 38;
oResizeRange.WrapText = true;
//헤더의 내부 색상을 채 웁니다.
oResizeRange.Interior.ColorIndex = 36;
//열을 수식으로 채우고 숫자 형식을 적용합니다.
oResizeRange = oWS.get_Range("E2", "E6").get_Resize(Missing.Value, iNumQtrs);
oResizeRange.Formula = "=RAND()*100";
oResizeRange.NumberFormat = "$0.00";
//판매 데이터 및 헤더에 테두리를 적용합니다.
oResizeRange = oWS.get_Range("E1", "E6").get_Resize(Missing.Value, iNumQtrs);
oResizeRange.Borders.Weight = Excel.XlBorderWeight.xlThin;
//판매 데이터에 대한 합계 수식을 추가하고 테두리를 적용합니다.
oResizeRange = oWS.get_Range("E8", "E8").get_Resize(Missing.Value, iNumQtrs);
oResizeRange.Formula = "=SUM(E2:E6)";
oResizeRange.Borders.get_Item(Excel.XlBordersIndex.xlEdgeBottom).LineStyle
= Excel.XlLineStyle.xlDouble;
oResizeRange.Borders.get_Item(Excel.XlBordersIndex.xlEdgeBottom).Weight
= Excel.XlBorderWeight.xlThick;
//선택한 데이터에 대한 차트를 추가합니다.
oWB = (Excel._Workbook)oWS.Parent;
oChart = (Excel._Chart)oWB.Charts.Add(Missing.Value, Missing.Value,
Missing.Value, Missing.Value);
//ChartWizard를 사용하여 선택한 데이터에서 새 차트를 만듭니다.
oResizeRange = oWS.get_Range("E2:E6", Missing.Value).get_Resize(
Missing.Value, iNumQtrs);
oChart.ChartWizard(oResizeRange, Excel.XlChartType.xl3DColumn, Missing.Value,
Excel.XlRowCol.xlColumns, Missing.Value, Missing.Value, Missing.Value,
Missing.Value, Missing.Value, Missing.Value, Missing.Value);
oSeries = (Excel.Series)oChart.SeriesCollection(1);
oSeries.XValues = oWS.get_Range("A2", "A6");
for (int iRet = 1; iRet <= iNumQtrs; iRet++)
{
oSeries = (Excel.Series)oChart.SeriesCollection(iRet);
String seriesName;
seriesName = "=\"Q";
seriesName = String.Concat(seriesName, iRet);
seriesName = String.Concat(seriesName, "\"");
oSeries.Name = seriesName;
}
oChart.Location(Excel.XlChartLocation.xlLocationAsObject, oWS.Name);
//데이터를 덮지 않도록 차트를 이동하십시오.
oResizeRange = (Excel.Range)oWS.Rows.get_Item(10, Missing.Value);
oWS.Shapes.Item("Chart 1").Top = (float)(double)oResizeRange.Top;
oResizeRange = (Excel.Range)oWS.Columns.get_Item(2, Missing.Value);
oWS.Shapes.Item("Chart 1").Left = (float)(double)oResizeRange.Left;
}
}
}
코드에 대부분 주석을 달아 두었습니다. 큰 맥락을 이해하는데 문제는 없겠지만, 엔지엠에서 커스텀 모듈을 개발하기 위한 몇가지 규칙들에 대해 알아야 합니다. 이런 중요한 부분들은 꼭! 암기하고 넘어가야 합니다. 아래 코드에서 ":" 콜론을 기준으로 좌측은 클래스입니다. 우측은 상속받는 클래스 또는 인터페이스입니다. 프로그래밍 강좌가 아니라서 더 자세하게 설명은 하지 않겠지만, 중요한건 좌측은 사용자가 만드는 클래스라는 점입니다. 우측은 엔지엠에서 제공하는 라이브러리의 클래스 또는 인터페이스입니다.
public class ExcelModel : NGM.Models.Interface.BaseCustomToolModel
아무것도 없는 코드에서 엔지엠의 커스텀 모듈 클래스를 상속(Inheritance) 받으면 기본적인 코드를 생성할 수 있게됩니다.
다른 시스템에서 사용하려면 클래스에 public 한정자 또는 제한자를 설정해줘야 합니다. 한정자나 제한자나 같은 의미로 사용되지만, 해석에 따라 다르게 말합니다. Access Modifier(접근 한정자 또는 접근 제한자)라고 부릅니다. 한정자는 여러 종류가 있지만, 이 부분은 직접 찾아서 학습하시길 바랍니다. 엔지엠 커스텀 모듈을 개발하려면 public만 알면 되지만, 복잡한 모듈이라면 반드시 알아야 하는 부분입니다^^;
아래는 엔지엠 에디터의 사용자 도구에 표시되는 카테고리를 설정하는 코드입니다. 기본 생성은 아래와 같이 자동으로 만들어집니다.
public override string DisplayCategory => throw new NotImplementedException();
이렇게 바꿔주면~ 에디터의 사용자 도구에 카테고리가 "엑셀 예제"로 표시됩니다.
public override string DisplayCategory => "엑셀 예제";
아래 속성은 이 액션의 이름을 설정하는 부분입니다.
public override string DisplayName => throw new NotImplementedException();
"테스트 1"로 바꿔주세요~
public override string DisplayName => "테스트 1";
엔지엠 에디터의 사용자 도구 상자를 보면 "엑셀 예제" 카테고리에 "테스트 1" 이름으로 보여지는걸 알 수 있습니다. 당연한 이야기겠지만~ 카테고리 이름이 같으면 액션들이 자동으로 그루핑(Grouping)됩니다. 엑셀 예제 아래 화면 캡쳐 카테고리처럼요^^; 이렇게하면 유사한 기능들끼리 그룹으로 관리할 수 있고 찾기가 용이해집니다. 물론, 카테고리를 잘 세분화하고 용도에 맞는 이름을 지어주는게 중요하죠.
마지막으로 Execute가 있습니다. 사실 다른 상속 클래스들은 몇가지 더 존재하지만, 여기에서 깊이 다루지는 않겠습니다. 커스텀 모듈 개발에 대해 궁금하신 분들은 [ 여기 ] 강좌를 읽어보세요^^
public override void Execute()
이 부분은 스크립트에서 액션이 실행될 때 호출되는 메소드입니다. 그렇기 때문에 이 액션이 실행될 때 무언가 해야 한다면 이곳에서 코딩해야 합니다. 그래서 이 안에 엑셀 관련 코드들이 존재합니다. 이 부분은 어느정도 코드안에 주석(// 로 시작하는 부분)을 달아 두었으므로 이해하는데 크게 어려움(?)은 없을겁니다. 잘 이해가지 않는 부분은 댓글로 남겨주시면 답변 달아드릴께요^^;
이제 오늘의 핵심인~ 상호 작용에 대해 알아보도록 하겠습니다. 상호 작용에 대해 설명하기 위해서 너무 많은 내용들을 위에 적은게 아닌가 걱정되기도 하네요. 위 내용을 읽다가 포기하진 않았는지 모르겠습니다-_-; 대부분은 여기까지 잘 참고 따라오셨으리라 믿고~ 출발하죠. 여기서부터는 엔지엠에서 제공하는 변수에 대한 이해가 있어야 합니다. 그렇지 않다면 아래 내용이 어떤 기능에 대해 설명하고 있는지 이해하기 어려울겁니다. 가능하면 메뉴얼의 변수부분을 학습하시고 이 글을 봐주세요.
using 마지막에 using System.ComponentModel을 추가해주세요.
using System;
using System.Reflection;
using System.Windows.Forms;
using Excel = Microsoft.Office.Interop.Excel;
using System.ComponentModel;
Data1 속성을 하나 추가했습니다. 속성은 읽기(get)와 쓰기(set)가 있는 특별한 메소드입니다. 이 부분도 원론적인 부분부터 설명하려면 내용이 방대해서... 그냥 특별한 메소드 형식이며 속성(Property: 프로퍼티)이라고 알면 되겠습니다. 참고로, 언어별로 차이는 있지만 스페셜 메소드가 존재하며 이런 차이점에 대해서 잘 알고 있는것도 개발자로써 중요합니다.
[Category("Data")]
[Description("엑셀의 셀에 입력할 데이타 1입니다.")]
public string Data1 { get; set; }
동일한 속성을 몇개 더 추가해주세요. 예제는 속성을 4개 만들었습니다.
using System;
using System.Reflection;
using System.Windows.Forms;
using Excel = Microsoft.Office.Interop.Excel;
using System.ComponentModel;
namespace CustomExcelExampleModule
{
public class ExcelModel : NGM.Models.Interface.BaseCustomToolModel
{
public override string DisplayCategory => "엑셀 예제";
public override string DisplayName => "테스트 1";
[Category("Data")]
[Description("엑셀의 셀에 입력할 데이타 1입니다.")]
public string Data1 { get; set; }
[Category("Data")]
[Description("엑셀의 셀에 입력할 데이타 2입니다.")]
public string Data2 { get; set; }
[Category("Data")]
[Description("엑셀의 셀에 입력할 데이타 3입니다.")]
public string Data3 { get; set; }
[Category("Data")]
[Description("엑셀의 셀에 입력할 데이타 4입니다.")]
public string Data4 { get; set; }
아래 내용을 수정해야 합니다.
//셀 단위로 표 머리글을 추가합니다.
oSheet.Cells[1, 1] = "First Name";
oSheet.Cells[1, 2] = "Last Name";
oSheet.Cells[1, 3] = "Full Name";
oSheet.Cells[1, 4] = "Salary";
이렇게 수정하세요. 표 머리글을 사용자가 직접 설정할 수 있도록 하는 부분입니다.
//셀 단위로 표 머리글을 추가합니다.
oSheet.Cells[1, 1] = this.Data1;
oSheet.Cells[1, 2] = this.Data2;
oSheet.Cells[1, 3] = this.Data3;
oSheet.Cells[1, 4] = this.Data4;
아래 그림을 참고해서 빌드(컴파일) 하세요. 하단의 로그에 빌드 성공 메시지가 표시됩니다.
프로젝트에서 우클릭 후 빌드 선택
컴파일된 모듈을 가져오기 위해 아래 그림과 같이 처리합니다. 프로젝트에서 우클릭 후 "파일 탐색기에서 폴더 열기"를 선택하세요. 그리고, "bin/release" 폴더에 "CustomExcelExampleModule.dll"을 복사하세요.
복사한 모듈을 아래 폴더에 복사해줍니다.
C:\Users\<사용자 계정>\Documents\NGM6\ToolExtension
이제 엔지엠 에디터를 실행하세요. 그리고, 새 스크립트에 커스텀 모듈 액션을 추가하세요.
Data1~4까지 속성이 추가된걸 확인할 수 있습니다.
데이타를 입력하세요. 여러분들은 임의로 넣어도 됩니다.
실행하면 아래와 같이 제목이 Data1~Data4로 변경된걸 알 수 있습니다.
엔지엠 커스텀 모듈은 기본적인 내용은 자동으로 생성하고 연동됩니다. 대표적으로 변수죠. 코딩으로 변수쪽을 처리하지 않더라도 사용할 수 있습니다. 물론, 아이디를 설정하면 참, 거짓에 따라 로직도 이동할 수 있죠. 상당히 파워풀(?)한 기능이지만 진입 장벽이 높다는 단점이 있습니다. 크게 복잡한 코딩이 아니라면 간단한 데이타 조작같은 경우는 직접 처리하는게 더 효율적입니다. 회사의 경우에는 엔지엠소프트웨어에서 업무 로직을 개발해드릴 수 있습니다. 엔지엠에서 제공하는 액션으로 구현하기 어렵거나 비효율적인 작업은 커스텀으로 처리하고, 소스를 직접 관리하는게 더 좋은 선택일 수 있습니다. 핵심적인 부분을 커스텀 모듈로 회사에서 공유한다면 더 많은 부분에서 무인 자동화 시스템을 구축할 수 있습니다. 많은 비용을 절감하고 휴먼 에러 발생을 제로화 할 수 있죠^^; 오늘은 여기까지입니다. 궁금한 내용은 댓글로 남겨주세요~
개발자에게 후원하기
추천, 구독, 홍보 꼭~ 부탁드립니다.
여러분의 후원이 빠른 귀농을 가능하게 해줍니다~ 답답한 도시를 벗어나 귀농하고 싶은 개발자~
감사합니다~
- 이전글[고급 사용자] 1. 네이버에서 비트코인 관련 뉴스 크롤링 및 엑셀 저장하기. (Crawling Bitcoin-related news on Naver and saving it in Excel.) 21.06.05
- 다음글1부 - 커스텀 액션으로 액셀 매크로 만들기. 21.03.27
댓글목록
등록된 댓글이 없습니다.