[Java] POI 라이브러리 사용 : 엑셀 다운로드 로직 구현하기

2022. 11. 15. 11:12 JAVA/Java

[Java] POI 라이브러리 사용 : 엑셀 다운로드 로직 구현하기

 

- 의존성 추가

 

Spring Boot 경우 build.gradle에 Gradle  dependency 추가

 

compile group: 'org.apache.poi', name: 'poi', version: '3.13'

 

Spring 경우 pom.xml Maven dependency 추가

 

<dependency>
	<groupId>org.apache.poi</groupId>
	<artifactId>poi</artifactId>
	<version>3.13-beta1</version>
</dependency>

 

 

- Haenny 엑셀 다운로드

 

다음과 같은 두 개의 클래스로 엑셀 다운로드 로직을 구현하였다.

 

참고로 엑셀에 입력될 데이터는 EgovMap이 아닌 VO List 형태를 전제로 구현하였다.

 

 

DownloadExcel.java

 

import java.io.IOException;
import java.net.URLEncoder;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFFont;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class DownloadExcel {
	private static final Logger LOGGER = LoggerFactory.getLogger(DownloadExcel.class);
	private HttpServletResponse response;
	private HSSFWorkbook wb;

	public DownloadExcel(String filename, HttpServletRequest request, HttpServletResponse response, HSSFWorkbook wb) {
		
		this.response = response;
		this.wb = wb;
		
		try {
			String browser = CommonVariable.getBrowser(request);	// 브라우저 확인하는 메서드
			String encodedFilename = null;
			
			if (browser.equals("MSIE")) {
				encodedFilename = URLEncoder.encode(filename, "UTF-8").replaceAll(
						"\\+", "%20");
			} else if (browser.equals("Firefox")) {
				encodedFilename = "\""
						+ new String(filename.getBytes("UTF-8"), "8859_1") + "\"";
			} else if (browser.equals("Opera")) {
				encodedFilename = "\""
						+ new String(filename.getBytes("UTF-8"), "8859_1") + "\"";
			} else if (browser.equals("Chrome")) {
				StringBuffer sb = new StringBuffer();
				for (int i = 0; i < filename.length(); i++) {
					char c = filename.charAt(i);
					if (c > '~') {
						sb.append(URLEncoder.encode("" + c, "UTF-8"));
					} else {
						sb.append(c);
					}
				}
				encodedFilename = sb.toString();
			} else {
				throw new IOException("Not supported browser");
			}
			
			response.setHeader("Content-Disposition", "attachment; filename=" + encodedFilename);

			if("Opera".equals(browser)){
				response.setContentType("application/octet-stream;charset=UTF-8");
			}
			
		} catch (IOException e) {
			LOGGER.error("[Excel Download Error]");
		}
	}
	
	public void writeExcel(){
		ServletOutputStream sos = null;
		try{
			sos = response.getOutputStream();
			wb.write(sos);
			sos.flush();
		}catch(IOException e){
			LOGGER.error("[Excel Download Error]");
		}finally{
			if(sos!=null){ 
				try {
					sos.close();
				} catch (IOException e) {
					LOGGER.error("[Excel Download Error]");
				}
			}
			if(wb!=null){
				try {
					wb.close();
				} catch (IOException e) {
					LOGGER.error("[Excel Download Error]");
				}
			}
		}
	}
	
	public CellStyle headStyle(){
		
		HSSFFont font = wb.createFont();
		font.setBold(true);
		font.setColor(IndexedColors.WHITE.index);
		
		CellStyle style = wb.createCellStyle();
		style.setFont(font);
		style.setWrapText(true);
		style.setFillForegroundColor(IndexedColors.ROYAL_BLUE.index);
		style.setFillPattern(CellStyle.SOLID_FOREGROUND);
		style.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
		style.setAlignment(HSSFCellStyle.ALIGN_CENTER);
		style.setBorderLeft(HSSFCellStyle.BORDER_THIN);
		style.setBorderRight(HSSFCellStyle.BORDER_THIN);
		style.setBorderTop(HSSFCellStyle.BORDER_THIN);
		style.setBorderBottom(HSSFCellStyle.BORDER_THIN);
		
		return style;
	}
	
	public CellStyle bodyStyle(){
		
		HSSFFont font = wb.createFont();
		
		CellStyle style = wb.createCellStyle();
		style.setFont(font);
		style.setWrapText(true);
		style.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
		style.setAlignment(HSSFCellStyle.ALIGN_CENTER);
		style.setBorderLeft(HSSFCellStyle.BORDER_THIN);
		style.setBorderRight(HSSFCellStyle.BORDER_THIN);
		style.setBorderTop(HSSFCellStyle.BORDER_THIN);
		style.setBorderBottom(HSSFCellStyle.BORDER_THIN);
		
		return style;
	}
}

 

 

ExportExcelVOList.java

 

import java.lang.reflect.Field;
import java.text.SimpleDateFormat;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

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.ss.usermodel.CellStyle;

public class ExportExcelVOList {
	private HttpServletRequest req;
	private HttpServletResponse res;
	protected HSSFSheet[] sheetArray;
	protected HSSFWorkbook wb;
	protected DownloadExcel downloadExcel;
	protected String colN[];
	protected CellStyle headStyle;
	protected CellStyle bodyStyle;

	public ExportExcelVOList(HttpServletRequest request, HttpServletResponse response) {
		this.req = request;
		this.res = response;
		this.sheetArray = new HSSFSheet[1];
		this.wb = new HSSFWorkbook();
		if(CommonVariable.chkNull(request.getParameter("colN[]"))){
			this.colN = request.getParameter("colN[]").split(",");
		}
		this.setExcelFormat();
	}
	
	/* 필수 exl.setListData 로 가져온 HSSFSheet를 넘겨줘야함 */
	public void setSheetArray(int index, HSSFSheet st) {
		sheetArray[index] = st;
	}
	
	/* 필수 모든 세팅이 완료된 후 엑셀 다운로드 받는 메소드 */
	public void actionDownloadExcel() {
		downloadExcel.writeExcel();
	}
	
	/* 파라메터로 넘어온 엑셀명 혹은 다운받은 일시를 파일명으로 엑셀파일 생성*/
	private void setExcelFormat(){
		long time = System.currentTimeMillis();
		SimpleDateFormat day = new SimpleDateFormat("yyyyMMddhhmmss");
		String excelnm = day.format(time);
		this.downloadExcel = new DownloadExcel(excelnm+".xls", req, res, wb);
		this.headStyle = downloadExcel.headStyle();
		this.bodyStyle = downloadExcel.bodyStyle();
	}
	
	/* 컬럼 스타일 세팅 및 컬럼제목 입력*/
	private void setColumnStyle(HSSFSheet st, HSSFRow title, int width, int addIdx){
		for (int i = 0; i < colN.length; i++) {
			title.createCell(i + addIdx).setCellValue(colN[i].replaceAll("&gt;=", ">="));
			title.getCell(i + addIdx).setCellStyle(headStyle);
			st.setColumnWidth(i + addIdx, width);
		}
	}
	
	/* VO data를 파라메터로 생성할 각 시트에 세팅*/ 
	public HSSFSheet setDataToExcelList(List<?> data, String sheetName) {
		HSSFSheet st = null;
		try {
			st = wb.createSheet(sheetName);
			HSSFRow titleRow = st.createRow(0);
			titleRow.setHeight((short) 400);
			setColumnStyle(st, titleRow, 6000, 0);	// colN을 이용한 컬럼명 처리
			for (int i = 0; i < data.size(); i++) {
				HSSFRow row = st.createRow(st.getLastRowNum() + 1);
				row = setRowData(row, data.get(i), 0);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return st;
	}
	
	/* VO data를 파라메터로 해당 데이터 셀에 입력*/ 
	private HSSFRow setRowData(HSSFRow row, Object data, int stIdx) throws IllegalArgumentException, IllegalAccessException{
		int edIdx = 0;
		for(Field field : data.getClass().getDeclaredFields()) {
			field.setAccessible(true);
			Object value = field.get(data);
			row.createCell(stIdx+edIdx).setCellValue(value.toString());
			edIdx++;
		}
		for(int i=0; i<edIdx; i++){
			row.getCell(stIdx+i).setCellStyle(bodyStyle);
		}
		return row;
	}
}

 

- Controller 사용방법

 

1.  단일 시트인 경우

 

@RequestMapping(value="/excel", method = RequestMethod.POST, produces="text/plain;Charset=UTF-8")
public void exceldownload(MultipartHttpServletRequest req, HttpServletResponse res) throws Exception {
	// 파라메터로 받아온 key값(조회 조건)
	String key = req.getParameter("key").replaceAll("&quot;","");	
	try {
		// DB에 key값에 일치하는 데이터 리스트 조회    
		List<ExcelVO> list = service.getExcelList(key);	
		
		// 생성자함수로 생성 후 초기 세팅
		ExportExcelVOList exl = new ExportExcelVOList(req, res);	
		// 파라메터 : 조회한 리스트, 시트명
		HSSFSheet st = exl.setDataToExcelList(list, "sheet1");		
		exl.setSheetArray(0, st);	// 1개의 시트 사용하는 경우
		exl.actionDownloadExcel();	// 엑셀 다운로드
	} catch (Exception e) {
		e.printStackTrace();
	}
}

 

2. 복수 시트인 경우

 

@RequestMapping(value="/excel", method = RequestMethod.POST, produces="text/plain;Charset=UTF-8")
public void exceldownload(MultipartHttpServletRequest req, HttpServletResponse res) throws Exception {
	String key = req.getParameter("key").replaceAll("&quot;","");	
	try {
		List<ExcelVO> list = service.getExcelList(key);	
		
		ExportExcelVOList exl = new ExportExcelVOList(req, res);	
		for(int i=0; i<2; i++){	// 3개의 sheet 생성할 경우
			HSSFSheet st = exl.setDataToExcelList(list, "sheet"+i);	
			exl.setSheetArray(i, st);	
		}
		exl.actionDownloadExcel();	// 엑셀 다운로드
	} catch (Exception e) {
		e.printStackTrace();
	}
}

 

 

 

 

 

엑셀 다운로드에 해당하는 DownloadExcel.java 와 ExportExcelVOList.java는 사용중인 코드를 그대로 복사해서 넣은 것이다.

 

그러니 모르는게 있다면 언제든 댓글^__^

 

 

 

아 ! 이번 게시물은 VO List 데이터로 엑셀 데이터를 입력했는데, 다음에는 EgovMap 데이터로 엑셀 다운로드 받는 게시물을 가져오겠다.

 

 

 

 


 

 

CommonVariable Class 추가 - 2022.02.11

 

CommonVariable 같은 경우는 제가 임의로 만든 클래스이고, 공통적으로 쓰이는 변수나 메서드를 담은 클래스입니다.

위에서 사용한 getBrowser 와 chkNull 메서드는 브라우저를 체크하는 메서드, null 체크 메서드로 getBrowser 메서드는 다음과 같이 구성되어있습니다.

public static String getBrowser(HttpServletRequest req) {
		String header = request.getHeader("User-Agent");
		if (header.indexOf("MSIE") > -1) {
			return "MSIE";
		} else if (header.indexOf("Chrome") > -1) {
			return "Chrome";
		} else if (header.indexOf("Opera") > -1) {
			return "Opera";
		} else if (header.indexOf("Firefox") > -1) {
			return "Firefox";
		} else if (header.indexOf("Mozilla") > -1) {
			if (header.indexOf("Firefox") > -1) {
				return "Firefox";
			}else{
				return "MSIE";
			}
		}
		return "MSIE";
}

 

출처 : https://haenny.tistory.com/103