반응형
엑셀 업로드 기능을 만들어보려고 한다.
하나하나 만들어놓고 나중에 편하게 꺼내서 사용하자...!
여기저기 블로그 및 사수분께 감사하며...! Begin~
1). 엑셀업로드 관련 라이브러리 POI 추가 <pom.xml>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.16</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.16</version>
</dependency>
2). 엑셀 유틸 모듈 작성 <ExcelUtil.java>
한군데에 몰아놓고 꺼내쓰기 좋다.
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.imageio.ImageIO;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.util.CellReference;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
public class ExcelUtil {
/**
* 엑셀파일을 읽어서 Workbook 객체를 리턴한다.
* XLS와 XLSX 확장자를 비교한다.
* @param filePath
* @return
*/
public static Workbook getWorkbook(String filePath) {
/*
* FileInputStream은 파일의 경로에 있는 파일을
* 읽어서 Byte로 가져온다.
*
* 파일이 존재하지 않는다면은
* RuntimeException이 발생된다.
*/
FileInputStream fis = null;
try {
fis = new FileInputStream(filePath);
}catch(FileNotFoundException e) {
throw new RuntimeException(e.getMessage(), e);
}
Workbook workbook = null;
/*
* 파일의 확장자를 체크해서 .XLS 라면 HSSFWorkbook에
* .XLSX라면 XSSFWorkbook에 각각 초기화 한다.
*/
if(filePath.toUpperCase().endsWith(".XLS")) {
try {
workbook = new HSSFWorkbook(fis);
}catch (IOException e) {
throw new RuntimeException(e.getMessage(), e);
}
}else if(filePath.toUpperCase().endsWith(".XLSX")) {
try {
workbook = new XSSFWorkbook(fis);
}catch (IOException e) {
throw new RuntimeException(e.getMessage(), e);
}
}
return workbook;
}
/**
* Cell에 해당하는 Column Name을 가젼온다(A,B,C..)
* 만약 Cell이 Null이라면 int cellIndex의 값으로
* Column Name을 가져온다.
* @param cell
* @param cellIndex
* @return
*/
public static String getName(Cell cell, int cellIndex) {
int cellNum = 0;
if(cell != null) {
cellNum = cell.getColumnIndex();
}
else {
cellNum = cellIndex;
}
return CellReference.convertNumToColString(cellNum);
}
public static String getValue(Cell cell) {
String value = "";
if(cell == null) {
value = "";
}else {
switch(cell.getCellType()) {
case Cell.CELL_TYPE_FORMULA :
value = cell.getCellFormula();
break;
case Cell.CELL_TYPE_NUMERIC :
value = (int)cell.getNumericCellValue() + ""; //(int)형변환 미변환시 소수점 발생가능
break;
case Cell.CELL_TYPE_STRING :
value = cell.getStringCellValue();
break;
case Cell.CELL_TYPE_BOOLEAN :
value = cell.getBooleanCellValue() + "";
break;
case Cell.CELL_TYPE_ERROR :
value = cell.getErrorCellValue() + "";
break;
case Cell.CELL_TYPE_BLANK :
value = "";
break;
default :
value = cell.getStringCellValue();
}
}
return value;
}
/**
* 엑셀파일 내용 읽어오기
* Service에서 이 함수 호출
* @param excelReadOption
* @return
*/
public static List<Map<String, String>> excelRead(ExcelReadOption excelReadOption) {
//엑셀 파일 자체
//엑셀파일을 읽어 들인다.
//FileType.getWorkbook() <-- 파일의 확장자에 따라서 적절하게 가져온다.
Workbook wb = getWorkbook(excelReadOption.getFilePath());
/**
* 엑셀 파일에서 첫번째 시트를 가지고 온다.
*/
Sheet sheet = wb.getSheetAt(0);
// System.out.println("Sheet 이름: "+ wb.getSheetName(0));
// System.out.println("데이터가 있는 Sheet의 수 :" + wb.getNumberOfSheets());
/**
* sheet에서 유효한(데이터가 있는) 행의 개수를 가져온다.
*/
int numOfRows = sheet.getPhysicalNumberOfRows();
int numOfCells = 0;
Row row = null;
Cell cell = null;
String cellName = "";
/**
* 각 row마다의 값을 저장할 맵 객체
* 저장되는 형식은 다음과 같다.
* put("A", "이름");
* put("B", "게임명");
*/
Map<String, String> map = null;
/*
* 각 Row를 리스트에 담는다.
* 하나의 Row를 하나의 Map으로 표현되며
* List에는 모든 Row가 포함될 것이다.
*/
List<Map<String, String>> result = new ArrayList<Map<String, String>>();
/**
* 각 Row만큼 반복을 한다.
*/
for(int rowIndex = excelReadOption.getStartRow() - 1; rowIndex < numOfRows; rowIndex++) {
/*
* 워크북에서 가져온 시트에서 rowIndex에 해당하는 Row를 가져온다.
* 하나의 Row는 여러개의 Cell을 가진다.
*/
row = sheet.getRow(rowIndex);
if(row != null) {
//가져온 Row의 Cell의 개수를 구한다.
//한개의 행마다 몇개의 cell이 있는지 리턴
//numOfCells = row.getPhysicalNumberOfCells();
//마지막 셀의 숫자 리턴
numOfCells = row.getLastCellNum();
/*
* 데이터를 담을 맵 객체 초기화
*/
map = new HashMap<String, String>();
/*
* cell의 수 만큼 반복한다.
*/
for(int cellIndex = 0; cellIndex < numOfCells; cellIndex++) {
/*
* Row에서 CellIndex에 해당하는 Cell을 가져온다.
*/
cell = row.getCell(cellIndex);
/*
* 현재 Cell의 이름을 가져온다
* 이름의 예 : A,B,C,D,......
*/
cellName = getName(cell, cellIndex);
/*
* 추출 대상 컬럼인지 확인한다
* 추출 대상 컬럼이 아니라면,
* for로 다시 올라간다
*/
if( !excelReadOption.getOutputColumns().contains(cellName) ) {
continue;
}
/*
* map객체의 Cell의 이름을 키(Key)로 데이터를 담는다.
*/
map.put(cellName, getValue(cell));
}
//행번호 추가
map.put("rowNum", String.valueOf(rowIndex+1));
/*
* 만들어진 Map객체를 List로 넣는다.
*/
result.add(map);
}
}
return result;
}
}
3). Excel 파일을 읽을 때 옵션을 설정하는 java 파일을 만든다. <ExcelReadOption.java>
추가적으로 필요한 옵션을 설정해 줘도 좋다.
import java.util.ArrayList;
import java.util.List;
public class ExcelReadOption {
//엑셀파일의 경로
private String filePath;
//추출할 컬럼명
private List<String> outputColumns;
//추출을 시작할 행 번호
private int startRow;
public String getFilePath() {
return filePath;
}
public void setFilePath(String filePath) {
this.filePath = filePath;
}
public List<String> getOutputColumns() {
List<String> temp = new ArrayList<String>();
temp.addAll(outputColumns);
return temp;
}
public void setOutputColumns(List<String> outputColumns) {
List<String> temp = new ArrayList<String>();
temp.addAll(outputColumns);
this.outputColumns = temp;
}
public void setOutputColumns(String ... outputColumns) {
if(this.outputColumns == null) {
this.outputColumns = new ArrayList<String>();
}
for(String ouputColumn : outputColumns) {
this.outputColumns.add(ouputColumn);
}
}
public int getStartRow() {
return startRow;
}
public void setStartRow(int startRow) {
this.startRow = startRow;
}
}
4). 사용코드
원하는 서비스로직에 추가해서 사용하면 될것같다.
MultipartHttpServletRequest multipart = (MultipartHttpServletRequest) req;
MultipartFile excelFile = multipart.getFile("excelFile");
//파일 저장후 읽어오자
//로컬 파일 저장 경로 => 내가 설정한 파일 경로를 사용하려고 한다.
String uploadRealPath = env.getProperty("excelFileTms.upload.realPath");
//엑셀파일을 읽기 위해서 서버에 저장
File destFile = new File(uploadRealPath + File.separator + "excel" + File.separator + excelFile.getOriginalFilename());
try{
//경로가 없으면 경로생성
if(!destFile.exists()) {
destFile.mkdirs();
}
excelFile.transferTo(destFile);
}catch(Exception e){
resultMap.put("result", Constant.XHR_REQUEST_FAIL);
resultMap.put("msg", "Excel Upload Failed");
return resultMap;
}
//엑셀 파일 읽기
ExcelReadOption excelReadOption = new ExcelReadOption();
excelReadOption.setFilePath(destFile.getAbsolutePath()); //파일경로 추가
excelReadOption.setOutputColumns("A","B","C","D","E","F","G","H","I","J","K","L","M"); //추출할 컬럼 설정
excelReadOption.setStartRow(2); //추출할 시작 행 설정
List<Map<String, String>> excelContent = ExcelUtil.excelRead(excelReadOption);
excelContent에 엑셀에서 내가 끄집어낸 데이터들이 담겨있으니 꺼내쓰면 끝
다음에는 다운로드를 만들어야지...
다운로드는 제약조건 걸어서 보내는 방법을 공부해보도록 하자...
반응형
'Spring-JSP' 카테고리의 다른 글
[Spring-JSP] Rest API 사용하기 (0) | 2021.03.03 |
---|---|
[Spring-JSP] 엄청쉬운 Apache Poi Excel 양식다운로드 기능구현 / 테이블 참조 (0) | 2021.02.23 |
[Spring-JSP] Custom Annotation만드는 방법 정리 (0) | 2021.02.09 |
[Spring-JSP] 파일업로드 처리 / 파일(단,다중) + 추가정보 @ModelAttribute (0) | 2021.01.29 |
[Spring-JSP]문자열 출력시 공백 및 줄바꿈 적용 (0) | 2021.01.22 |