[Java] Apache POIを用いたExcelファイルの作成

## はじめに
日頃、会社で学んできたことの中からアウトプットしていきます。
今回は、「Apache POI」を用いてエクセルファイル(.xlsx)を作成します。

# Apache POIとは
<img width="310" alt="apache_logo.png" src="https://qiita-image-store.s3.amazonaws.com/0/215568/dfa5f968-281c-b97f-b915-c647d1954a22.png">
Javaアプリケーションから「Excel」や「Word」といった
Microsoft製品のフォーマットファイルを読み書きするためのAPIです。

# 事前準備
以下のURLより、ライブラリを用意します。
今回は、最新バージョンの「poi-bin-3.17-20170915」を使用します。(2017年12月時)

- Apache POI
  - URL : https://poi.apache.org/download.html


# 主に利用するクラス
- WorkBookクラス(ワークブックに関して扱う)
- Sheetクラス(シートに関して扱う)
- Rowクラス（行に関して扱う）
- Cellクラス(セルに関して扱う)
- CellStyleクラス(セルのスタイルに関して扱う)

これらのクラスには、「HSSF」と「XSSF」の２種類のフォーマットがあります。

# 「HSSF」と「XSSF」って？
エクセルのファイルフォーマットのことを指します。

|種類|ファイルフォーマット|
|:---:|:---:|
|HSSF|Excel2003までのファイルフォーマット|
|XSSF|Excel2007におけるOOXML形式のファイルフォーマット|

# Excelファイルの作成
## ワークブック
```java:
/**
 * ワークブックの作成
*/

// HSSF
HSSFWorkbook workbook1 = new HSSFWorkbook();

// XSSF
XSSFWorkbook workbook2 = new XSSFWorkbook();

// Workbook (HSSFWorkbookクラス及びXSSFWorkbookクラスの共通インタフェース)
Workbook workbook3 = new HSSFWorkbook();

Workbook workbook4 = new XSSFWorkbook();
```

##シート
```java:
/**
 　* シートの作成、シートの指定
*/

// HSSF
HSSFSheet sheet1 = workbook1.createSheet();

// シート名による指定
sheet1 = workbook1.getSheet("シート1");

// インデックスによる指定 (シート番号は0から始まる)
sheet1 = workbook1.getSheetAt(0);
	    
// XSSF
XSSFSheet sheet2 = workbook2.createSheet();
/* シートの指定は省略 */
	    
// Sheet (HSSFSheetクラス及びXSSFSheetクラスに共通するインターフェース)
Sheet sheet3 = workbook3.createSheet();
/* シートの指定は省略 */

Sheet sheet4 = workbook4.createSheet();
/* シートの指定は省略 */
```
##行
```java:
/**
　　* 行の作成、行の指定
*/

// HSSF (行番号は0から始まる)
HSSFRow row1 = sheet1.createRow(0);
	    
// 行の指定 (行番号は0から始まる)
row1 = sheet1.getRow(0);
	    
// XSSF (行番号は0から始まる)
XSSFRow row2 = sheet2.createRow(0);
/* 行の指定は省略 */
	    
// Row (HSSFRowクラス及びXSSFRowクラスに共通するインターフェース)
Row row3 = sheet3.createRow(0);
/* 行の指定は省略 */
	    
Row row4 = sheet4.createRow(0);
/* 行の指定は省略 */
```
## セル
```java:
/**
　　* セルの作成、セルの指定、セルに値を設定
*/

// HSSF (セル番号は0から始まる)
HSSFCell cell1 = row1.getCell(0);
	    
// セルの指定 (セル番号は0から始まる)
cell1 = row1.getCell(0);
	    
// セルに値を設定　(文字列を設定)
/*
　　* セルに設定できるデータ型
　　* Boolean型        : setCellValue(boolean value) 
　　* String型         : setCellValue(java.lang.String value)
　　* RichTextString型 : setCellValue(RichTextString value)
　　* Calendar型       : setCellValue(java.util.Calendar value)
　　* Date型           : setCellValue(java.util.Date value)
　　* Double型         : setCellValue(double value) 
*/
cell1.setCellValue("テスト1");
	    
// XSSF (セル番号は0から始まる)
XSSFCell cell2 = row2.getCell(0);
/* セルの指定・セルの値設定は省略 */
	    
// Cell (HSSFCellクラス及びXSSFCellクラスに共通するインターフェース)
Cell cell3 = row3.getCell(0);
/* セルの指定・セルの値設定は省略 */
	    
Cell cell4 = row4.getCell(0);
/* セルの指定・セルの値設定は省略 */
```
## セルのスタイル
```java:
/**
　* セルのスタイル作成、セルのスタイル指定、セルのスタイルに値を設定
*/

// HSSF
HSSFCellStyle cellstyle1 = workbook1.createCellStyle();
	    
// セルのスタイルに値を設定 (フォント)
Font font = workbook1.createFont();
font.setFontName("ＭＳ ゴシック");
font.setColor(IndexedColors.RED.getIndex());
font.setFontHeightInPoints((short)14);
cellstyle1.setFont(font);
	    
// セルのスタイル指定
cell1.setCellStyle(cellstyle1);
	    
// XSSF
XSSFCellStyle cellstyle2 = workbook2.createCellStyle();
/* セルスタイルの指定・セルスタイルの値設定は省略 */
	    
// CellStyle (HSSFCellStyleクラス及びXSSFCellStyleクラスに共通するインターフェース)
CellStyle cellstyle3 = workbook3.createCellStyle();
/* セルスタイルの指定・セルスタイルの値設定は省略 */
	    
CellStyle cellstyle4 = workbook4.createCellStyle();
/* セルスタイルの指定・セルスタイルの値設定は省略 */
```

セルのスタイルは、量が多いので以下URLを参照。
URL : https://poi.apache.org/apidocs/org/apache/poi/ss/usermodel/CellStyle.html

##エクセルファイルの出力
```java:
/**
 * エクセルファイルの出力
*/

// 出力ファイルの設定
FileOutputStream outExcelFile = null;	    
String outputPath = "出力したいファイルパス";
String fileName = "test.xlsx";

try{
     // ファイルを出力
     outExcelFile = new FileOutputStream(outputPath + fileName);
     workbook1.write(outExcelFile);
}catch(Exception e){
     System.out.println(e.toString());
}finally{
     try {
	    outExcelFile.close();
     }catch(Exception e){
	    System.out.println(e.toString());
     }
}
```

# 作ってみた
今回は、試しに「九九の表」をエクセル出力させてみました。
エクセルに表示させたいだけなので、かなり無理やりに作っています。
ご了承ください。

<img width="640" alt="kuku.png" src="https://qiita-image-store.s3.amazonaws.com/0/215568/be87e596-de0b-a1ee-b1d7-e6e8e1e82955.png">


```java:
package apache_poi.kuku;

import java.io.FileOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;

import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.FillPatternType;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.apache.poi.xssf.usermodel.XSSFFont;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;



/**
 * 九九の表をエクセルファイルに出力
 * @author s-tsuchida
 *
 */
public class Kuku_Poi {
	
	public static void main(String[] args) {
		
		// ワークブック
		XSSFWorkbook workBook = null;
		// シート
		XSSFSheet sheet = null;
		// 出力ファイル
		FileOutputStream outPutFile = null;
		// 出力ファイルパス
		String outPutFilePath = null;
		// 出力ファイル名
		String outPutFileName = null;
		
		// エクセルファイルの作成
		try {
			
			// ワークブックの作成
			workBook = new XSSFWorkbook();
			
			// シートの設定
			sheet = workBook.createSheet();
			workBook.setSheetName(0, "九九の表");
			sheet = workBook.getSheet("九九の表");
			
			// 初期行の作成
			XSSFRow row = sheet.createRow(2);
			
			// 「タイトル」のセルスタイル設定
			XSSFCellStyle titleCellStyle = workBook.createCellStyle();
			XSSFCell cell = row.createCell(7);
			XSSFFont titleFont = workBook.createFont();
			titleFont.setFontName("ＭＳ ゴシック");
			titleFont.setFontHeightInPoints((short)36);
			titleFont.setUnderline(XSSFFont.U_SINGLE);
			titleCellStyle.setFont(titleFont);
			cell.setCellStyle(titleCellStyle);
			
			// セルに「タイトル」を設定
			cell.setCellValue("九九の表");
			
			// 「表のヘッダ」のセルスタイル設定
			XSSFCellStyle headerCellStyle = workBook.createCellStyle();
			XSSFFont headerFont = workBook.createFont();
			headerFont.setFontName("ＭＳ ゴシック");
			headerFont.setFontHeightInPoints((short)25);
			headerCellStyle.setFont(headerFont);
			headerCellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
			headerCellStyle.setAlignment(HorizontalAlignment.CENTER);
			headerCellStyle.setFillForegroundColor(IndexedColors.PALE_BLUE.index);
			headerCellStyle.setBorderTop(BorderStyle.MEDIUM);
			headerCellStyle.setBorderBottom(BorderStyle.MEDIUM);
			headerCellStyle.setBorderRight(BorderStyle.MEDIUM);
			headerCellStyle.setBorderLeft(BorderStyle.MEDIUM);
			
			// セルに「表のヘッダ」を設定
			row = sheet.createRow(5);
			// 横
			for(int i = 3 , j = 0; i < 13 ; i++, j++) {
				cell = row.createCell(i);
				cell.setCellStyle(headerCellStyle);
				if(i == 3) {
					cell.setCellValue("");
				}else {
					cell.setCellValue(j);
				}
			}
			// 縦
			for(int i = 6 , j = 1 ; i < 15 ; i++, j++) {
				row = sheet.createRow(i);
				cell = row.createCell(3);
				cell.setCellStyle(headerCellStyle);
				cell.setCellValue(j);
			}
			
			// 「計算結果」のセルスタイル設定
			XSSFCellStyle resultCellStyle = workBook.createCellStyle();
			XSSFFont resultFont = workBook.createFont();
			resultFont.setFontName("ＭＳ ゴシック");
			resultFont.setFontHeightInPoints((short)25);
			resultCellStyle.setFont(resultFont);
			resultCellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
			resultCellStyle.setAlignment(HorizontalAlignment.CENTER);
			resultCellStyle.setFillForegroundColor(IndexedColors.WHITE.index);
			resultCellStyle.setBorderTop(BorderStyle.MEDIUM);
			resultCellStyle.setBorderBottom(BorderStyle.MEDIUM);
			resultCellStyle.setBorderRight(BorderStyle.MEDIUM);
			resultCellStyle.setBorderLeft(BorderStyle.MEDIUM);
			
			// セルに「表のヘッダ」を設定
			double num1 = 0;
			double num2 = 0;
			double result = 0;
			for(int i = 6 ; i < 15 ; i++) {
				for(int j = 4 ; j < 13 ; j++) {
					// 九九の計算
					num1 = sheet.getRow(5).getCell(j).getNumericCellValue();
					num2 = sheet.getRow(i).getCell(3).getNumericCellValue();
					result = num1 * num2;

					row = sheet.getRow(i);
					cell = row.createCell(j);
					cell.setCellStyle(resultCellStyle);
					cell.setCellValue(result);
				}
			}
			
			// エクセルファイルを出力
			try {
				
				// 現在の日付を取得
				Date date = new Date();
				SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
				
				//ファイルパス・ファイル名の指定
				outPutFilePath = "出力したいファイルパス";
				outPutFileName = "kuku_" + dateFormat.format(date).toString() +  ".xlsx";
				
				// エクセルファイルを出力
				outPutFile = new FileOutputStream(outPutFilePath + outPutFileName);
				workBook.write(outPutFile);
				
				System.out.println("「" + outPutFilePath + outPutFileName + "」を出力しました。");
				
			}catch(IOException e) {
				System.out.println(e.toString());
			}
			
		}catch(Exception e) {
			System.out.println(e.toString());
		}
	
	}

}

```

# まとめ
今回、初めて「Apache POI」を利用しましたが、
思った以上に操作が簡単で使いやすいと感じました。
まだ手探り感が否めないため、今後も勉強してまいります。