본문 바로가기

밥벌이1 - S/W/Java

Java 프로그램에서 POI로 Excel파일을 조작하자

다음 내용은 일본의 월간 JavaWorld 2006 1월호에 게재된 내용을 번역한 것입니다.

지금은 이해하고 개발할 수준은 아니지만 , 필요할 때가 있을 것 같아서 .....

 

 

POI Excel파일을 조작하자

Java프로그램으로 Office문서를 조작하는 방법

 

POI Java프로그램으로 마이크로소프트사의 Office문서를 조작하기 위한 컴포넌트 군이다. POI에 의해서 Java프로그램으로 Excel 파일의 생성 및 불러오기 방법과, Excel 파일에 한글 데이터를 설정하는 경우에 필요한 처리에 대해서 설명한다.

 

Office 문서 조작을 용이하게 하는 컴포넌트 군

통상, Java EE 애플리케이션은, 클라이언트의 인터페이스로 Web 브라우저를 사용하며, 클라이언트의 OS에 의존하지 않고 동작한다. 그러나, 인트라넷으로 구축된 업무 시스템의 경우, 클라이언트 PC OS Windows인 경우가 많다. , 이러한 환경에서 시스템 데이터를 변경하는 경우에, 클라이언트 PC에서 파일을 편집하는 경우도 있을 것이다. 예를 들면, “Web 애플리케이션을 사용해서 다운로드 한 데이터를 Excel 파일로 편집하고 다시 업로드해서 데이터베이스에 반영시킨다와 같은 경우이다.

이런 경우, Java EE 애플리케이션에서 잘 쓰여지는 것은, 데이터를 수납하는 파일로써 CSVComma Separated Values)형식 파일을 쓰는 방법이다. CSV 파일은, Excel 에서도 불러올 수 있지만, 그 실체는 값을 콤마(,)로 구분하여 열거한 텍스트이다. 따라서, Java 프로그램에서도 편하게 생성하거나, 불러들이거나 할 수 있어 상당히 취급하기 편하다. 그러나, 조금 복잡한 요소(매크로를 포함하거나, 여러 워크시트를 갖고 있는 Excel 파일을 취급하고 싶은 경우 등)가 제시되면 CSV 파일로는 처리할 수 없기도 있다.

이러한 경우에 위력을 발휘하는 것이, Apache Jakarta 프로젝트가 제공하는 파일 조작용 컴포넌트 군 POI 이다.<화면1>

 

화면1:POI의 홈페이지 화면

 

POI 는 마이크로소프트사의 OLEObject Linking and Embedding, 윈도우에서 애플리케이션 간에 데이터를 공유하기 위한 구조)2로 정해진 복잡한 도큐먼트 형식(Excel, Word ) 의 파일을, Java 프로그램에서 취급하기 위한 컴포넌트 군이다.

원래, POI 는 개발 프로젝트명 이었지만, 같은 프로젝트에서 개발된 컴포넌트 군의 총칭으로 사용되고 있다. POI 프로젝트는, 현재, 다음과 같은 컴포넌트를 제공하고 있다.

 

●POIFSPOI Filesystem

복합 도큐먼트 형식의 파일을 불러오기 위한 컴포넌트 군의 기본이 되는 컴포넌트

●POI HSSFHorrible Spreadsheet Format

마이크로소프트사의 Excel97 형식 파일을 불러오기 위한 컴포넌트

●POI HPSFHorrible Property Set Format):

파일, 속성(파일 작성자명, 최종변경일 등)의 포맷을 조작하기 위한 컴포넌트

 

이들 컴포넌트를 잘 이용하면, Excel 파일을 취급하는 Java 애플리케이션도 간단하게 작성할 수 있다. POI 컴포넌트는 모두 Java로 작성되어 있고, 파일을 조작하기 위한 API도 풍부하게 제공되고 있다. 따라서, Java 프로그램에 적용하는 것도 간단하게 할 수 있다.

 

POI 를 이용하기 위한 준비

이번에는 앞서 열거한 컴포넌트에서 POI HSSF(이하, HSSF. 내부에서는 POIFS를 사용하고 있다.)를 설명하고, Java 프로그램에서 Excel 파일을 조작하는 방법을 설명한다.

우선, POI WEB 사이트에서, 파일(poi-bin-2.5.1-final-20040804.zip)을 다운로드 한다. HSSF를 이용하려면, 압축을 풀고 「poi-2.5.1-final-20040804.jar」파일을 애플리케이션의 클래스패스에 복사해두면 좋다.

 

Excel 파일 생성

HSSF에서 Excel 파일을 조작하기 위하여 API가 다수 제공되고 있다. 더구나, 이용 방법도 너무나 간단하기 때문에, HSSF를 이용한 프로그램을 보면, 직감적으로 그 사용법을 이해할 수 있을 것이다.

여기에서, 우선, Excel 파일을 신규로 생성하는 프로그램을 보자. <리스트1>의 프로그램은, 워크시트 하나를 갖고, 1행에 있는 2개의 셀에 각각 문자열 “CellData”와 정수 “123”을 셋트한 Excel 파일 “sample1.xls”를 생성하는 것이다. , 이것을 실행하면 <화면2>와 같은 파일을 얻을 수 있다.

 

<리스트1>HSSF를 사용하여,Excel파일을 생성하는 프로그램(Sample1.java)
package jwsample;
 
import java.io.FileOutputStream;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
 
public class Sample1 {
   public static void main(String[] args) {
      try {
         (new Sample1()).go();
      } catch (Exception ex) {
         System.err.println(ex);
      }
   }
 
   /**
    * 단순한 데이터 시트를 작성한다
    */
   void go() throws Exception {
      // Excel 파일을 표시하는 워크북 오브젝트를 생성    (1)
      HSSFWorkbook wb = new HSSFWorkbook();    
 
      // 「sheet1」라는 이름의 워크시트를 표시하는 오브젝트 생성    (2)
      HSSFSheet sheet1 = wb.createSheet("sheet1");    
 
      // 행의 작성    (3)
      HSSFRow row0 = sheet1.createRow(0);    
 
      // 행에 셀의 데이터를 설정    
      row0.createCell((short)0).setCellValue("CellData"); (4)
      row0.createCell((short)1).setCellValue(123);    
 
      // 워크북 오브젝트를 파일로써 출력    
      FileOutputStream fileOut = new FileOutputStream("sample1.xls"); (5)
      wb.write(fileOut);
      fileOut.close();    
   }
}


<화면2> <리스트1>의 프로그램에 의해 생성된 Excel 파일 (sample1.xls)


이 프로그램의 처리 흐름은 아래와 같다.

리스트1-(1)Excel파일을 표시하는 워크북 오브젝트를 생성

리스트1-(2):워크시트를 표시하는 오브젝트를 생성

리스트1-(3):행의 작성

리스트1-(4):행에 셀의 데이터를 설정

리스트1-(5):워크북 오브젝트를 파일로 출력

리스트를 읽어보면, 정말 단순 명료하게 기술되어 Excel 파일을 생성한다는 것을 바로 알 수 있을 것이다. 이 프로그램을 컴파일 / 실행하면, 작업 디렉토리에 「sample1.xls」가 출력된다.(샘플 파일은 첨부하였다.)

 

Excel 파일의 불어오기

다음으로, 기존에 있는 Excel 파일을 읽어, 셀의 데이터를 추출하여 보자, 그 프로그램 예는 <리스트 2>와 같다.

<리스트 2> Excel 파일을 읽어, 데이터를 추출하는 프로그램(Sample2.java)
package jwsample;
 
import java.io.FileInputStream;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
 
public class Sample2 {
   public static void main(String[] args) {
      try {
         (new Sample2()).go();
      } catch (Exception ex) {
         System.err.println(ex);
      }
   }
 
   void go() throws Exception {
 
      // Excel 파일 불러오기
      FileInputStream fis = new FileInputStream("sample1.xls");
      POIFSFileSystem fs = new POIFSFileSystem(fis);
 
      // 워크북 오브젝트의 취득
      HSSFWorkbook wb = new HSSFWorkbook(fs);
 
      // 총 워크시트수의 취득
      int sheets = wb.getNumberOfSheets();
 
      // 워크시트별로 데이터를 취득
      for (int sheetIdx = 0; sheetIdx < sheets; sheetIdx++) {
 
         // 워크시트를 표시하는 오브젝트의 취득    (1)
         HSSFSheet sheet = wb.getSheetAt(sheetIdx);    
 
         // 워크시트에 있는 첫행과 마지막행의 인덱스를 취득    
         int firstRow = sheet.getFirstRowNum(); (2)
         int lastRow = sheet.getLastRowNum();    
 
         // 행 별로 데이터를 취득    
         for (int rowIdx = firstRow; rowIdx <= lastRow; rowIdx++) {
 
            // 행을 표시하는 오브젝트의 취득
            HSSFRow row = sheet.getRow(rowIdx);
 
            // 행에 데이터가 없는 경우
            if (row == null) continue;
 
            // 행에서 첫셀과 마지막 셀의 인덱스를 취득
            short firstCell = row.getFirstCellNum();
            short lastCell = row.getLastCellNum();
 
            // 셀 별로 데이터를 취득
            for (short cellIdx = firstCell;
               cellIdx <= lastCell; cellIdx++) {
               String data = null;
 
               // 셀을 표시하는 오브젝트를 취득
               HSSFCell cell = row.getCell(cellIdx);
 
               // 빈 셀인 경우
               if (cell == null) continue;
  (3)
               // 셀에 있는 데이터의 종류를 취득
               int type = cell.getCellType();
 
               // 데이터 종류별로 데이터를 취득    
               switch (type) {     
                  case HSSFCell.CELL_TYPE_BOOLEAN:    
                     boolean bdata = cell.getBooleanCellValue();    
                     data = String.valueOf(bdata);    
                     break;    
                  case HSSFCell.CELL_TYPE_NUMERIC:    
                     double ddata = cell.getNumericCellValue();    
                     data = String.valueOf(ddata);    
                     break;  (4)  
                  case HSSFCell.CELL_TYPE_STRING:    
                     data = cell.getStringCellValue();    
                     break;    
                  case HSSFCell.CELL_TYPE_BLANK:    
                  case HSSFCell.CELL_TYPE_ERROR:    
                  case HSSFCell.CELL_TYPE_FORMULA:    
                  default:    
                     continue;    
               }    
               // 데이터 출력
               System.out.println(data);
            }     
         }
      }
   }
}

 

이 프로그램에는, Excel 파일내의 모든 워크 시트에서, 데이터를 읽도록 처리하고 있다. 우선, Excel 파일에 포함된 총 워크시트 수를 취득하고, 각 워크시트를 표시하는 오브젝트를 순서대로 추출한다<리스트2-(1)>. 다음으로, 워크시트 별로 최초의 행과 최후의 행의 인덱스를 취득하여<리스트2-(2)>, 그 값을 기준으로 처리를 반복하여 셀을 표시하는 오브젝트를 모두 취득한다<리스트2-(3)>. 마지막으로, 그 데이터의 종류(자형 / 정수형 / 논리형)을 조사하여, 적당한 메소드를 써서 데이터를 추출하면 된다<리스트2-(4)>.

또한, 여기서는 데이터가 없는 행과 셀은 무시하도록 하고 있지만, 필요에 따라 불러온 파일이 Excel 형식에 따라고 있는가혹은 적절한 데이터가 입력되어 있는가와 같은 체크 처리 추가도 간단하게 실현 가능하다.

 

Excel 파일을 조작하는 다양한 기능

HSSF, Excel 파일의 생성 / 불러오기 용 API 이외에도, 다음과 같은 목적으로 사용할 수 있는 API도 준비되어 있다.

괘선 지정

색 지정

셀 결합

폰트 지정

인쇄 범위 지정

머리글/바닥글 지정

날짜 지정

이러한 API를 사용하여 Excel 파일에 관한 일반적인 조작은 거의 모두 Java 프로그램에서도 처리할 수 있을 것이다. 또한, Excel 파일의 입출력은 클래스 java.io.InputStream/OutputStream(샘플에서는 FileInputStream/FileOutputStream로 사용하고 있다.)을 이용하므로 Web 애플리케이션 등과 같이 네트워크를 통해서도 파일의 송수신을 처리하는 경우도 특별히 문제는 발생되지 않는다.

 

한글 처리

마지막으로 Java 프로그램 내에서 Excel 파일에 한글 데이터를 설정하는 경우의 처리에 대해서 설명한다. 이러한 경우, 셀을 표시하는 오브젝트에 대해서 ENCODING 을 설정한 후, 한글 문자열을 셋트한다.

그 예는 다음과 같다.


HSSFCell cell = row1.createCell((short)0);
cell.setEncoding(HSSFCell.ENCODING_UTF_16);
cell.setCellValue("セル2-3");

 

한글로 워크시트명을 쓰는 경우도, 한글 데이터를 설정하는 경우와 동일하게 ENCODING 을 지정하면 된다. 다음 예에서는, ENCODING UTF_16을 설정하여 워크시트에 시트2”라고 이름을 붙이고 있다.

 

HSSFSheet sheet2 = wb.createSheet();
wb.setSheetName(1, "시트2", HSSFWorkbook.ENCODING_UTF_16);

 

또한, 한글로 기술된 데이터를 Excel 파일에서 불러오는 때에는, 특별하게 ENCODING를 설정할 필요가 없다.

 

이상과 같이, POI를 구성하는 컴포넌트 중에서 HSSF Java 프로그램에서 Excel 파일을 조작하는 방법에 대해서 설명했다. HSSF을 사용하면, Java 프로그램에서 Excel 파일을 간단하게 취급할 수 있다고 느낄 것이다.

더욱이, 현재 POI 프로젝트에서는 Java 프로그램으로 Word 파일을 조작하는 컴포넌트인 「POI HWPFHorrible Word Processor Format)」의 개발도 진행되고