[C#] NPOI를 이용하여 Excel를 읽어드리고 다시 출력하기


Development note/C#  2019. 5. 14. 23:37

안녕하세요. 명월입니다.

 

지난 포스팅에서 C#에서 엑셀파일을 만드는 라이브러리 NPOI에 대해서 설명했습니다.

링크 - [C#] NPOI를 이용한 엑셀 파일 만들기

이어서 이번에는 처음부터 만드는 것이 아니라 템플릿을 읽어 드려서 필요한 데이터만 바꾸는 방법으로 설명하겠습니다.

 

먼저 하나의 예제 데이터를 만들었습니다.

예제 파일 첨부입니다.

Test.xls
0.03MB

예제 데이터는 첫번째 컬럼은 월, 2번째 컬럼은 기온 평균, 3번째 컬럼은 오전 기온, 4번째 컬럼은 오후 기온으로 그래프는 평균을 나타내는 값으로 했습니다.

 

이제 프로그램을 작성하겠습니다.

먼저 NUGET을 통해 NPOI를 다운, 참조하겠습니다.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
//공통 NPOI
using NPOI;
using NPOI.SS.UserModel;
//표준 xls 버젼 excel시트
using NPOI.HSSF;
using NPOI.HSSF.UserModel;
//확장 xlsx 버젼 excel 시트
using NPOI.XSSF;
using NPOI.XSSF.UserModel;

namespace NPOIExample
{
  class Program
  {
    static void Main(string[] args)
    {
      new Program();
      Console.WriteLine("Press Any Key...");
      Console.ReadKey();
    }
    public Program()
    {
      var version = "xls";
      //var version = "xlsx";
      // Workbook 취득.
      var workbook = GetWorkbook(@"d:\work\Test.xls", version);

      // Workbook안에 시트 취득.
      var sheet = workbook.GetSheetAt(0);

      // Sheet에서 셀 취득 후 데이터 설정
      // 1월 오전
      GetCell(sheet, 1, 2).SetCellValue(-5);
      // 1월 오후
      GetCell(sheet, 1, 3).SetCellValue(0);
      // 2월 오전
      GetCell(sheet, 2, 2).SetCellValue(-10);
      // 2월 오후
      GetCell(sheet, 2, 3).SetCellValue(-5);
      // 3월 오전
      GetCell(sheet, 3, 2).SetCellValue(0);
      // 3월 오후
      GetCell(sheet, 3, 3).SetCellValue(2);
      // 4월 오전
      GetCell(sheet, 4, 2).SetCellValue(4);
      // 4월 오후
      GetCell(sheet, 4, 3).SetCellValue(10);
      // 5월 오전
      GetCell(sheet, 5, 2).SetCellValue(10);
      // 5월 오후
      GetCell(sheet, 5, 3).SetCellValue(15);
      // 6월 오전
      GetCell(sheet, 6, 2).SetCellValue(18);
      // 6월 오후
      GetCell(sheet, 6, 3).SetCellValue(25);
      // 7월 오전
      GetCell(sheet, 7, 2).SetCellValue(23);
      // 7월 오후
      GetCell(sheet, 7, 3).SetCellValue(28);
      // 8월 오전
      GetCell(sheet, 8, 2).SetCellValue(25);
      // 8월 오후
      GetCell(sheet, 8, 3).SetCellValue(31);
      // 9월 오전
      GetCell(sheet, 9, 2).SetCellValue(25);
      // 9월 오후
      GetCell(sheet, 9, 3).SetCellValue(29);
      // 10월 오전
      GetCell(sheet, 10, 2).SetCellValue(15);
      // 10월 오후
      GetCell(sheet, 10, 3).SetCellValue(25);
      // 11월 오전
      GetCell(sheet, 11, 2).SetCellValue(11);
      // 11월 오후
      GetCell(sheet, 11, 3).SetCellValue(17);
      // 12월 오전
      GetCell(sheet, 12, 2).SetCellValue(5);
      // 12월 오후
      GetCell(sheet, 12, 3).SetCellValue(9);

      // 함수값 재 설정
      for (int i = 1; i <= 12; i++)
      {
        GetCell(sheet, i, 1).SetCellFormula(String.Format("AVERAGE(C{0}:D{0})", i + 1));
      }

      WriteExcel(workbook, @"d:\work\result." + version);
    }
    // Workbook 읽어드리기
    public IWorkbook GetWorkbook(string filename, string version)
    {
      using (var stream = new FileStream(filename, FileMode.Open, FileAccess.Read))
      {
        //표준 xls 버젼
        if ("xls".Equals(version))
        {
          return new HSSFWorkbook(stream);
        }
        //확장 xlsx 버젼
        else if ("xlsx".Equals(version))
        {
          return new XSSFWorkbook(stream);
        }
        throw new NotSupportedException();
      }
    }

    // Sheet로 부터 Row를 취득, 생성하기
    public IRow GetRow(ISheet sheet, int rownum)
    {
      var row = sheet.GetRow(rownum);
      if (row == null)
      {
        row = sheet.CreateRow(rownum);
      }
      return row;
    }
    // Row로 부터 Cell를 취득, 생성하기
    public ICell GetCell(IRow row, int cellnum)
    {
      var cell = row.GetCell(cellnum);
      if (cell == null)
      {
        cell = row.CreateCell(cellnum);
      }
      return cell;
    }
    public ICell GetCell(ISheet sheet, int rownum, int cellnum)
    {
      var row = GetRow(sheet, rownum);
      return GetCell(row, cellnum);
    }
    public void WriteExcel(IWorkbook workbook, string filepath)
    {
      using (var file = new FileStream(filepath, FileMode.Create, FileAccess.Write))
      {
        workbook.Write(file);
      }
    }
  }
}

기존 0과 2로 되어있던 데이터를 입력해서 위 결과 값처럼 값이 바뀌면서 그래프의 모습도 바뀌었습니다. 소스 중에 함수 재 설정 부분이 있습니다. 이유는 모르겠으나 C열과 D열의 데이터가 바뀌어도 함수식으로 재 계산되어 B열이 값이 바뀌지 않습니다.

그래서 그 부분에 Formula함수를 써서 다시 재 입력을 하면 C열과 D열의 값이 계산되어 입력됩니다.

 

실제 업무에서도 엑셀을 다루는 영역이면 프로그램 안에서 엑셀을 1부터 만들어서 출력하기 보다는 스타일이나 그래프, 서식등을 미리 템플릿에 만들어 놓고 프로그램에서는 값만 넣어서 출력하는 형태로 많이 사용합니다. 물론 출력 값이 매우 동적으로 사양에 따라 엑셀 시트 모습이 천차 만별이면 어쩔 수 없지만, 그런 경우는 많지도 않고 정해진 포멧이 값만 바뀌는 형태가 대부분이기 때문에 위와 같이 많이 작성합니다.

 

첨부파일입니다.

NPOIExample.zip
0.29MB