package itn.let.utl.user.service; import java.beans.PropertyDescriptor; import java.lang.reflect.Method; import java.util.List; import org.apache.poi.hssf.usermodel.HSSFCellStyle; import org.apache.poi.hssf.usermodel.HSSFDataFormat; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.CellStyle; import org.apache.poi.ss.usermodel.HorizontalAlignment; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.VerticalAlignment; import org.apache.poi.xssf.streaming.SXSSFSheet; import org.apache.poi.xssf.streaming.SXSSFWorkbook; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; @Component public class ExcelUtil { private static final Logger log = LoggerFactory.getLogger(ExcelUtil.class); /** * 엑셀 파일을 방출합니다. * * @param voList 엑셀에 넣고 싶은 vo 리스트 형태로 넣습니다. * @param header 엑셀 해더 * @param order 헤더에 해당하는 내용의 vo 필드 이름을 작성합니다. 예를 들어 String userName; 필드의 1번째 해더이름을 "사용자 이름" 으로 정했으면 * 순서를 맞추어 1번째 order 배열에 "UserName" 이라는 글짜를 입력해줍니다(*주의:첫 문자는 대문자, 낙타체). 첫번째 컬럼에는 "줄번호"가 * 들어가는데, 이것에 대한 내용은 order에 값을 입력하지 않습니다. * @param width 컬럼 너비를 설정합니다. length가 해더의 length와 일치할 필요는 없습니다. * @param title * @throws Exception * @return SXSSFSheet * * 특징 : 해더보다 내용의 컬럼수가 많을 때 해당 줄의 컬럼은 cut, 해더 이름이 vo와 다르게 되면 해당 컬럼 출력 안됨 require : 날짜 포멧은 * 지원하지 않습니다. * * * *********************************************************************************************** * EX String title = "게시판 리스트"; * int[] width = {1500, 1500, 1500, 3000, 30000, 3000 }; * String[] header = {"번호", "게시판번호", "작성자", "제목", "내용", "작성일" }; * String[] order = { "Seq", "UserId", "Title", "Content", "RegDt" }; * => 첫번째 "번호"에 대한 order 이름이 비어있습니다. * * *********************************************************************************************** */ public static SXSSFWorkbook makeSimpleFruitExcelWorkbook(List voList, String[] header, String[] order, int[] width, String title) throws Exception { // 시트 생성 SXSSFWorkbook workbook = new SXSSFWorkbook(); SXSSFSheet sheet = workbook.createSheet(title); for (int i = 0; i < width.length; i++) { // JSP 2022.02.24 => width 변경 //sheet.setColumnWidth(0, width[width.length - (i + 1)]); sheet.setColumnWidth(i, width[i]); } int r = 2;// 줄부터 찍기 CellStyle headerstyle = workbook.createCellStyle(); headerstyle.setAlignment(HorizontalAlignment.CENTER); headerstyle.setVerticalAlignment(VerticalAlignment.CENTER); headerstyle.setBorderBottom(HSSFCellStyle.BORDER_THIN); // 헤더 행 생 Row headerRow = sheet.createRow(r); // 해더 값 채움 (우측 방향으로) Cell headerCell = null; for (int i = 0; i < header.length; i++) { headerRow.setHeight((short)512); headerCell = headerRow.createCell(i); headerCell.setCellStyle(headerstyle); headerCell.setCellValue(header[i]); } // 내용 행 및 셀 생성 Row bodyRow = null; Cell bodyCell = null; bodyRow = sheet.createRow(0); bodyCell = bodyRow.createCell(0); bodyCell.setCellValue(title);// 읽어온 데이터 표시 //System.out.println("voList.size()"); //System.out.println(voList.size()); //System.out.println(voList.size()); int c = 0;// 컬럼 for (Object vo : voList) { bodyRow = sheet.createRow(r + 1); bodyCell = bodyRow.createCell(0); //bodyCell.setCellValue(r + 1); // 첫 컬럼은 줄 번호 PropertyDescriptor pd; // 클래스의 필드 메소드를 찾아줌. 이름을 기존에 vo.setUserId() 란 메소드를 통해서만 호출이 가능 했다면, PropertyDescriptor는 이름만으로 메소드 // 호출이 가능함. 클래스가 변경 되어도 동일한 작동으로 getter&setter 호출이 가능하도록 도와줌 Method[] methods = vo.getClass().getDeclaredMethods(); // 메소드들 호출함 // 배열로 준 이름 과 같으면 해당 열 데이터 쓰기 for (int i = 0; i < order.length; i++) { for (Method method : methods) { // vo 내부 메소드 반복 // System.out.println("i :: "+ i + "methods : "+ methods); /*System.out.println("voList.method()"); System.out.println(method.getName());*/ if (method.getName().equals("get" + (order[i] == null ? "" : order[i]))) { // vo메소드 이름과 order의 이름 비교 // getter 호출 준비 String getMethodName = method.getName().substring(3); // getter의 이름 가져옴 pd = new PropertyDescriptor(getMethodName, vo.getClass()); // vo의 데이터 세팅 String cellData = (pd.getReadMethod().invoke(vo) != null ? pd.getReadMethod().invoke(vo) : "").toString(); bodyCell = bodyRow.createCell(c++); // 데이터 순서 if(getMethodName.equals("InstrFee") || getMethodName.equals("SpecialWorkAllow") || getMethodName.equals("DistanceAllow") || getMethodName.equals("TrafficFee") || getMethodName.equals("AcmdtFee") || getMethodName.equals("Amt") || getMethodName.equals("Cash") ){ // JSP 2022.02.22 => null 에러 try~catch 문 추가 try { double num = Double.parseDouble(cellData); CellStyle bodyStyle = workbook.createCellStyle(); bodyCell.setCellValue(num);// 읽어온 데이터 표시 bodyStyle.setDataFormat(HSSFDataFormat.getBuiltinFormat("#,##0")); bodyCell.setCellStyle(bodyStyle); } catch (Exception ex) { bodyCell.setCellValue(cellData); } }else { bodyCell.setCellValue(cellData);// 읽어온 데이터 표시 } //System.out.println("@@ : "+getMethodName +" --- " + cellData); } } } c = 0; r++; } return workbook; } }