2023. 12. 21. 21:56ㆍ개발/C#
2023.12.18 - [개발 기록/C#] - 모니터링 자동화 - Teamviewer 상태 관리
모니터링 자동화 - Teamviewer 상태 관리
2023.12.17 - [개발 기록/C#] - 모니터링 자동화 - 웹 크롤링 모니터링 자동화 - 웹 크롤링 C# Selenium 라이브러리를 활용해 모니터링 페이지의 데이터를 크롤링 테스트한다. 크롤링 함수 public bool GetMonit
iruk.tistory.com
웹 크롤링 / 팀뷰어 API 호출로 받아온 데이터를
엑셀 보고서 파일에 자동 Write하는 로직을 추가한다.
WriteExcel() bool형 함수
public bool WriteExcel(string filePath)
{
int retryCount = 0;
bool success = false;
bool flag = false;
Excel.Application excelApp = null;
Excel.Workbook workbook = null;
Excel.Worksheet worksheet = null;
endRow = companyListMgr.companyNameList.Count + startRow - 1;
try
{
if (ExcelClosed())
{
#region 엑셀파일 open 및 예외처리
while (retryCount < MaxRetries && !success)
{
try
{
excelApp = new Excel.Application();
excelApp.Visible = false;
//excelApp.WindowState = Excel.XlWindowState.xlMaximized;
workbook = excelApp.Workbooks.Open(filePath);
worksheet = (Excel.Worksheet)workbook.Sheets[1];
success = true;
}
catch (COMException ex)
{
if (ex.ErrorCode == -2147417846 || ex.ErrorCode == -2147418111) // 엑셀파일 이미 사용중 에러코드
{
Thread.Sleep(RetryInterval);
retryCount++;
}
else
{
return flag;
}
}
}
if (!success) // 엑셀파일 오픈 retry 10회 실패 시
{
return flag;
}
#endregion
WriteCompanyName(worksheet);
Thread.Sleep(300);
WriteTeamviewer(worksheet);
Thread.Sleep(300);
WriteReception(worksheet);
Thread.Sleep(300);
WriteDeviceTotal(worksheet);
Thread.Sleep(300);
WriteDeviceConnected(worksheet);
Thread.Sleep(300);
WriteDate(worksheet);
Thread.Sleep(300);
#region 엑셀파일 저장 및 메모리해제
workbook.Save();
workbook.Close();
excelApp.Quit();
ReleaseObject(worksheet);
ReleaseObject(workbook);
ReleaseObject(excelApp);
#endregion
flag = true;
return flag;
}
return flag;
}
catch
{
return flag;
}
}
일단 윈폼에서, 버튼 클릭으로 파일 찾기를 실행하고
선택된 파일의 경로를 저장해서
엑셀 Write 시 경로를 호출해 파일을 연다.
private bool ExcelClosed()
{
bool flag = false;
Process[] processes = Process.GetProcessesByName("EXCEL");
Process targetProcess = null;
foreach (Process process in processes) // 연동보고서 EXCEL 파일이 실행중인지 확인
{
if (process.MainWindowTitle.Contains("연동보고서"))
{
targetProcess = process;
break;
}
}
if(targetProcess == null)
{
flag = true;
return flag;
}
else // 실행중인 "연동보고서 .... " EXCEL 이 있으면
{
try
{
targetProcess.Kill();
if (targetProcess.HasExited)
{
flag = true;
}
return flag;
}
catch (Exception)
{
return flag;
}
}
}
이미 보고서 파일이 실행중인데,
또 보고서 파일을 열고 작업 시
충돌 가능성이 있어서
실행중인 보고서 파일은 종료하는 예외처리
일단 단순하게 엑셀 파일 명에 "연동보고서"를 체크하는데
더 세밀하게 관리하려면
내부 시트값을 읽거나..
뭐 여러가지 고민해봐야 될듯
현재는 사용자의 파일 인지상태를 가정하고 구상했다.
#region 엑셀파일 open 및 예외처리
while (retryCount < MaxRetries && !success)
{
try
{
excelApp = new Excel.Application();
excelApp.Visible = false;
//excelApp.WindowState = Excel.XlWindowState.xlMaximized;
workbook = excelApp.Workbooks.Open(filePath);
worksheet = (Excel.Worksheet)workbook.Sheets[1];
success = true;
}
catch (COMException ex)
{
if (ex.ErrorCode == -2147417846 || ex.ErrorCode == -2147418111) // 엑셀파일 이미 사용중 에러코드
{
Thread.Sleep(RetryInterval);
retryCount++;
}
else
{
return flag;
}
}
}
if (!success) // 엑셀파일 오픈 retry 10회 실패 시
{
return flag;
}
#endregion
region 으로 따로 구분한 부분은
단순 "엑셀 파일 실행" 및 "예외처리" 인데
함수 자체에 try catch 문이 있어
엑셀 실행 시 에러코드는 예외처리 제외할까 생각중이다.
catch 에서 전체 Exception 을 받아오면 되니까
굳이 이중으로 catch를 쓸 필요가 없는듯
아무튼 엑셀 파일이 정상적으로 열릴때까지 시도
WriteCompanyName(worksheet);
Thread.Sleep(300);
WriteTeamviewer(worksheet);
Thread.Sleep(300);
WriteReception(worksheet);
Thread.Sleep(300);
WriteDeviceTotal(worksheet);
Thread.Sleep(300);
WriteDeviceConnected(worksheet);
Thread.Sleep(300);
WriteDate(worksheet);
Thread.Sleep(300);
그 후, Write 할 데이터별로 구분한 함수들을 전부 실행한다.
수신율 / 장비 수/ 팀뷰어 등의 정보를 각각 개별 함수에서 Write
Thread.Sleep(300) 은, 바로 실행 시 누락되는 경우가 있어
최소한의 딜레이 시간을 잡았다.
private void WriteCompanyName(Excel.Worksheet worksheet)
{
for (int j = 0; j < companyListMgr.companyNameList.Count; j++)
{
worksheet.Cells[j+7, 3].Value = companyListMgr.companyNameList[j];
}
}
Write는 로직은 되게 간단하다.
보고서 양식을 이해한 상태에서,
작성할 양식의 행/열에 맞게 Value 를 입력한다.
ReleaseObject(worksheet);
ReleaseObject(workbook);
ReleaseObject(excelApp);
flag = true;
return flag;
모든 데이터 Write 가 완료되면
엑셀 종료 및 메모리 해제
private void ReleaseObject(object obj)
{
try
{
Marshal.ReleaseComObject(obj);
obj = null;
}
catch (Exception)
{
obj = null;
}
finally
{
GC.Collect();
}
}
이건 메모리 해제 및 가비지 수집 함수
문제점
지금까지 웹 크롤링 / 팀뷰어 API / 엑셀 Write 등의
기능 구현은 됐는데
한 가지 문제점이
프로그램 화면에서
버튼을 누르고
위 3가지 과정이 실행되면
1. 버튼 클릭
2. 사용자가 끝날때까지 대기
해야 한다.
애초에 처음부터 비동기로 설계를 했어야 했는데
웹 크롤링 / API / 엑셀 Write 기능 여부만 확인한다는게
로직을 다 구현해버려서
아무튼 비동기로 수정해야겠다.
프로세스 별 비동기로 처리하고
화면상에 로딩바? 현재상태? 를 나타내줄 예정
'개발 > C#' 카테고리의 다른 글
C# 반복문 변수 선언과 메모리에 관한 고찰 (0) | 2023.12.28 |
---|---|
모니터링 자동화 - 비동기 변경 (0) | 2023.12.24 |
모니터링 자동화 - Teamviewer 상태 관리 (1) | 2023.12.18 |
모니터링 자동화 - 웹 크롤링 (2) | 2023.12.17 |
모니터링 자동화 - 구상 (2) | 2023.12.17 |