티스토리 뷰
프로그램 내에서 워드 문서(마소 오피스나 리브레 오피스로 작성)를 새롭게 생성하거나, 기존 문서를 수정하거나 아니면 특정 양식에 필요한 내용을 반영하여 새로운 문서를 만드는 등의 작업을 하는 경우가 있다. 자동차 검사소에서 고객들이 받는 검사 결과지를 예로 들 수 있다. 각종 자동차 검사를 수행하면 다양한 검사 장비와 센서에서 올라온 값들을 검사원이 양식에 일일이 입력하는 것이 아니라 작업이 끝났다는 신호와 함께 보고서 출력을 지시하면 미리 준비된 양식에 해당 값을 자동으로 입력하여 출력하고 양식은 파일로 남겨 놓는 것이다. 우리나라 국민들이 받는 건강 검사의 경우도 마찬가지이다. 사람이 직접 입력하는 신상 정보와 검사 정보를 데이터베이스에 저장해 두었다가 미리 준비한 양식에 맞게 출력하는 것이다.
본 포스팅에서는 미리 준비한 양식 파일(*. docx)을 읽어서 적절한 곳에 필요한 내용을 입력하여 새로운 파일로 저장하고 해당 파일을 인쇄하는 방식으로 진행한다. 이 방식으로 하면 양식의 내용이 바뀌면 워드 문서만 수정하면 되므로 프로그램을 수정할 필요가 없다.
우선적으로 준비할 것은 양식 파일이다. 위의 그림처럼 *. docx 문서로 양식 파일을 작성하고 프로그램에서 입력할 부분에 대괄호를 이용해 마킹 작업을 한다. {A}처럼 표시하는 마커는 대괄호를 사용하지 않아도 되지만 양식 파일 문서 내에서 유일한 텍스트여야 한다. 또 한 가지 주의할 점은 프로그램에서는 폰트의 크기나 색상 등은 손대지 않고 텍스트만 마커 대신 프로그램에서 지정한 텍스트로 변경할 것이므로 마커 크기나 색상 등은 양식에서 적절하게 조정한다.
다음으로 진행할 것은 프로젝트 사용하는 라이브러리를 설치하는 것이다. 본 포스팅에서는 윈도우와 리눅스에서 모두 사용할 수 있는 NPOI를 적용했다. 위의 그림처럼 비주얼스튜디오에서 도구> 패키지 관리자 콘솔을 선택하여 콘솔을 열고 다음과 같은 명령으로 관련 패키지를 프로젝트에 적용한다.
NuGet\Install-Package SixLabors.Fonts -Version 1.0.0-beta19
NuGet\Install-Package NPOI -Version 2.6.0
관련 작업을 수행하는 소스 코드에는 다음과 같이 using문을 추가한다.
using NPOI.XWPF.UserModel;
XWPFDocument doc = null;
private bool phset_text(string ph, string valstr)
{
if (doc == null) return false;
foreach (var bele in doc.BodyElements)
{
if (bele is XWPFParagraph)
{
XWPFParagraph para = (XWPFParagraph)bele;
if (para.ParagraphText.Contains(ph))
{
para.ReplaceText(ph, valstr);
return true;
}
}
else if (bele is XWPFTable)
{
XWPFTable tbl = (XWPFTable)bele;
foreach (XWPFTableRow row in tbl.Rows)
{
foreach (ICell ic in row.GetTableICells())
{
if (ic is XWPFTableCell)
{
XWPFTableCell tableCell = (XWPFTableCell)ic;
foreach (var cele in tableCell.BodyElements)
{
if (cele is XWPFParagraph)
{
XWPFParagraph para = (XWPFParagraph)cele;
if (para.ParagraphText.Contains(ph))
{
para.ReplaceText(ph, valstr);
return true;
}
}
}
}
}
}
}
}
return false;
}
var ofile = File.OpenRead("test.docx"); //양식 파일 열기
doc = new XWPFDocument(ofile); //양식 파일 로드(NPOI)
//양식 내용 채우기
phset_text("{DAY}", DateTime.Now.ToString("yyyy-MM-dd"));
phset_text("{A}", "David");
phset_text("{B}", "1990-01-10");
//.......
var destfile = "David_" + DateTime.Now.ToString("yyyyMMdd") + @".docx"; //새 파일이름 만들기
var ws = File.Create(destfile); //새 파일 생성
doc.Write(ws); //새파일 쓰기(NPOI)
ws.Close(); //새파일 닫기
ofile.Close(); //양식 파일 닫기
//새 파일 인쇄
ProcessStartInfo psi = new ProcessStartInfo(destfile)
{
UseShellExecute = true,
Verb = "print",
RedirectStandardOutput = false,
CreateNoWindow = true
};
using (Process p = new Process { StartInfo = psi })
{
p.Start();
p.WaitForExit();
}
위의 코드는 양식 파일을 읽기 모드로 열고, NPOI 라이브러리 함수(XWPFDocument)로 해당 문서 로딩한 다음 phset_text 함수로 마커를 찾아 지정한 문자열로 바꾸는 작업을 수행한다. 장치에서 읽은 값 일수도, 프로그램에서 계산한 값 일수도, 데이터베이스에서 읽은 값 일수도, 통신으로 수신한 값 일수도 있다. phset_text 함수에서는 지정한 마커를 찾아서 로딩한 문서 내의 모든 요소를 검색하고 마커를 찾으면 텍스트를 변경하고 true를 리턴하며, 마커를 찾지 못하거나 실패하면 false를 리턴한다.
모든 마커에 대한 자료 입력 작업이 끝나면 새로운 문서 파일 이름을 지정하여 저장하고 모든 파일을 닫는다. 예제에서는 고객이름과 현재 일자를 기준으로 파일이름을 생성했다. 끝으로 새롭게 생성한 문서를 인쇄한다. 인쇄 작업은 마소 오피스나 리브레 오피스 등 현재 시스템에 설치된 프로그램 중에 *. docx 파일 열기에 대한 기본 프로그램으로 설정된 것을 통해 수행하므로 마소 오피스나 리브레 오피스가 기본적으로 설치되어 있어야 한다. 만약 인쇄 작업이 필요 없고 문서만 다루는 작업이라면 오피스 프로그램은 설치하지 않아도 된다.
'프로그래밍' 카테고리의 다른 글
파이썬 프로그램의 병목/정체 구간 찾기, 프로파일러 사용하기 (0) | 2023.09.05 |
---|---|
모드버스(Modbus) 응용 개발을 위한 준비 (0) | 2023.08.12 |
VSCode/ESP-IDF 환경에서 ESP32-S3 테스트 프로그램 적용하기 (0) | 2022.11.22 |
VSCode에서 ESP-IDF 개발 환경 설치하기 (0) | 2022.11.21 |
비주얼 스튜디오에서 안드로이드/iOS 앱 제작 맛보기 (0) | 2022.11.15 |