엑셀 파일 업로드 양식 체크 및 버전 체크 샘플 코드
다음과 같은 엑셀 양식이 있다. 11번가 셀러들이 상품 업로드할 때 사용하는 엑셀파일 양식을 일부 참고하였다.
코드는 다음과 같다.
// 마스터정보 엑셀 파일 업로드 처리
@RequestMapping(value = {"/excelUpload.do", "/business/excelUpload.do"})
@ResponseBody
public ResponseEntity<String> excelFileUpload(@ModelAttribute("uploadForm")FileUploadForm uploadForm, HttpServletResponse res, HttpServletRequest req, Model model)
{
Map<String, String> resultMap = new HashMap<>();
try
{
MultipartFile file = uploadForm.getFiles().get(0);
String category = req.getParameter("category");
if(file.isEmpty())
{
resultMap.put(ComnConst.ARGS_RETURN_CODE, "ERR_02");
return Utility.getJSONResponse(resultMap);
}
log.info("* dmnCond --> "+req.getParameter("dmnCond"));
//파일 타입 체크
boolean isExcel = Utility.isExcelFileExt(file.getOriginalFilename());
if (!isExcel) {
resultMap.put(ComnConst.ARGS_RETURN_CODE, "ERR_01");
return Utility.getJSONResponse(resultMap);
} else {
//
Workbook wokbook = ValidationCheckUtil.getWorkbook(file);
//엑셀 양식 버전 체크
String verStr = ValidationCheckUtil.getExcelTemplateVersion(wokbook);
if (!verStr.equals("ver. 1.0")) { //버전 정보 하드코딩 : 관리자페이지에서 버전 양식 관리가 필요한 경우 DB에서 버전 정보 조회 후 체크하세요!
resultMap.put(ComnConst.ARGS_RETURN_CODE, "ERR_03");
return Utility.getJSONResponse(resultMap);
}
//마스터 정보 엑셀 양식 체크
boolean isCorrect = ValidationCheckUtil.isCorrectExcelTemplate(wokbook, category);
if (!isCorrect) {
resultMap.put(ComnConst.ARGS_RETURN_CODE, "ERR_04");
return Utility.getJSONResponse(resultMap);
}
}
switch (category) {
case "EMP" : // 임직원 정보 업로드
excelDataUploadProc(uploadForm, res, req, new EmpExcelUploadService());
break;
case "DEPT" : // 부서 정보 업로드
excelDataUploadProc(uploadForm, res, req, new DeptExcelUploadService());
break;
case "PROD" : // 제품 정보 업로드
excelDataUploadProc(uploadForm, res, req, new ProdExcelUploadService());
break;
}
}
catch(Exception ex)
{
log.info(ex.toString());
resultMap.put(ComnConst.ARGS_RETURN_CODE, "ERR_911");
resultMap.put(ComnConst.ARGS_RETURN_STRING, ex.toString());
return Utility.getJSONResponse(resultMap);
}
return new ResponseEntity<>("[[]]", HttpStatus.OK);
}
// 엑셀 Workbook return 메소드
public static Workbook getWorkbook(MultipartFile multipart) {
Workbook book = null;
try
{
// File convFile = new File( multipart.getOriginalFilename());
// multipart.transferTo(convFile);
String fileName = multipart.getOriginalFilename();
FileInputStream fis = new FileInputStream(fileName);
if(fileName.toLowerCase().endsWith(".xls")) book = new HSSFWorkbook(fis);
else if(fileName.toLowerCase().endsWith(".xlsx")) book = new XSSFWorkbook(fis);
}
catch(Exception ex)
{
return null;
}
return book;
}
// 엑셀 버전 체크 메소드
public static String getExcelTemplateVersion(Workbook book) {
String versionInfo = "";
try
{
if(book.getNumberOfSheets() > 0)
{
Sheet versionRowsheet = book.getSheetAt(0);
// Row clsRow = versionRowsheet.getRow(0); //헤더 정보
Row clsRow = versionRowsheet.getRow(1); //2번째 행의 버전 정보 체크
versionInfo = clsRow.getCell(0).toString().trim(); // 첫번째 컬럼의 버전정보
}
}
catch(Exception ex)
{
return versionInfo;
}
return versionInfo;
}
// 엑셀 양식 체크 메소드
public static boolean isCorrectExcelTemplate(Workbook book, String category) {
boolean isCorrect = false;
try
{
if(book.getNumberOfSheets() > 0)
{
Sheet versionRowsheet = book.getSheetAt(0);
String name = versionRowsheet.getSheetName();
switch (category) {
case "EMP" :
if(name.equals("임직원등록")) isCorrect = true;
break;
case "DEPT" :
if(name.equals("부서등록")) isCorrect = true;
break;
case "PROD" :
if(name.equals("제품등록")) isCorrect = true;
break;
}
}
}
catch(Exception ex)
{
return isCorrect;
}
return isCorrect;
}
// 엑셀 Workbook 생성 및 버전 체크 메소드
public static String checkExcelTemplate(MultipartFile multipart) {
Workbook book = null;
String versionInfo = "";
try
{
String fileName = multipart.getOriginalFilename();
FileInputStream fis = new FileInputStream(fileName);
if(fileName.toLowerCase().endsWith(".xls")) book = new HSSFWorkbook(fis);
else if(fileName.toLowerCase().endsWith(".xlsx")) book = new XSSFWorkbook(fis);
if(book.getNumberOfSheets() > 0)
{
Sheet versionRowsheet = book.getSheetAt(0);
// Row clsRow = versionRowsheet.getRow(0); //헤더 정보
Row clsRow = versionRowsheet.getRow(1); //2번째 행의 버전 정보 체크
versionInfo = clsRow.getCell(0).toString().trim(); // 첫번째 컬럼의 버전정보
}
}
catch(Exception ex)
{
return versionInfo;
}
return versionInfo;
}
EmpExcelUploadService.java
import java.nio.charset.StandardCharsets;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.springframework.web.multipart.MultipartFile;
import com.ibatis.sqlmap.client.SqlMapClient;
public class EmpExcelUploadService extends AbstractXLFileUploadService
{
//엑셀 한글 칼럼명
public final String COLUMN_NAME_0 = "버전";
public final String COLUMN_NAME_1 = "이름";
public final String COLUMN_NAME_2 = "아이디";
public final String COLUMN_NAME_3 = "ADMIN사용여부";
public final String COLUMN_NAME_4 = "MR사용여부";
public final String COLUMN_NAME_5 = "사번";
public final String COLUMN_NAME_6 = "이메일";
public final String COLUMN_NAME_7 = "핸드폰번호";
public final String COLUMN_NAME_8 = "회사전화번호";
public final String COLUMN_NAME_9 = "영문이름";
//엑셀 한글 칼럼명
private String[] excelHeaderK =
{
COLUMN_NAME_0,
COLUMN_NAME_1,
COLUMN_NAME_2,
COLUMN_NAME_3,
COLUMN_NAME_4,
COLUMN_NAME_5,
COLUMN_NAME_6,
COLUMN_NAME_7,
COLUMN_NAME_8,
COLUMN_NAME_9,
};
@Override
protected int getNewFileId(MultipartFile file, PathInfo savePath)
{
int intResult = 0;
List<Sheet> sheet = getSheetMulti(file, savePath);
if (!sheet.isEmpty())
{
for (Sheet sheetAt : sheet)
{
intResult = saveSheetData(sheetAt);
}
}
else
{
intResult = ComnConst.RETURN_NO_DATA;
}
return intResult;
}
@Override
protected String getSheetXML(Sheet sheet)
{
return "";
}
@Override
protected boolean saveData(String strXML)
{
return false;
}
/**
* Sheet내에 Data를 저장한다.
* @param sheet
* @return
*/
int saveSheetData(Sheet sheet)
{
log.info("**saveEmpSheetData() START");
// 기본 정보 초기화
int intReturnCode = ComnConst.RETURN_UNKNOWN;
int intInsertCount = 0;
int intExcelRowCount = sheet.getLastRowNum();
int headIndex = 0; //헤더 위치
String strDmnCond = this.request.getParameter("dmnCond");
// String params = this.request.getParameter("params");
// String[] arrParam = params.split(",");
// String proId = arrParam[1];
SqlMapClient smc = commonDAO.getSqlMapClientTemplate("dataSource").getSqlMapClient();
try
{
UserModel userSession = Utility.getPrincipal();
smc.startTransaction();
smc.startBatch();
//기존 업로드 히스토리 삭제
// UBSalesParamMap delParam = new UBSalesParamMap();
// delParam.put("workTp", "D");
// delParam.put("userId", userSession.getUserId());
// smc.update("contact.saveSalesSourceExcel", delParam);
String inserttime = StringUtil.getNowTime();
if(intExcelRowCount > 3)
{
// 헤더 정보 (3번째 데이터) 부터 시작
String[] arsColumns = getHeaderColumns(sheet, headIndex);
if (arsColumns.length > 0)
{
log.info("* EMP DATA INSERT START");
// 저장될 Row 데이터 셋팅용 hashMap
Map<String, Object> mpRow = new HashMap<>();
List<String> userIdList = new ArrayList<>();
for(int intRowNum = 3;intRowNum <= intExcelRowCount ; intRowNum++)
{
// 데이터 정제 (sheet column 속성별 데이터 셋팅)
mpRow = rowToMap(sheet.getRow(intRowNum), arsColumns);
// 데이터 insert
if(mpRow!= null && !mpRow.isEmpty())
{
UBSalesParamMap excelRow = new UBSalesParamMap();
excelRow.put("workType", "EXCEL_REG_EMP_TEMP");
excelRow.put("dmnCond", strDmnCond);
excelRow.put("empNm", StringUtil.replaceString(mpRow.get(COLUMN_NAME_1)));
excelRow.put("empId", StringUtil.replaceString(mpRow.get(COLUMN_NAME_2)));
excelRow.put("adSiteUseYn", StringUtil.replaceString(mpRow.get(COLUMN_NAME_3)));
excelRow.put("mrSiteUseYn", StringUtil.replaceString(mpRow.get(COLUMN_NAME_4)));
excelRow.put("empNo", StringUtil.replaceString(mpRow.get(COLUMN_NAME_5)));
excelRow.put("emailAddr", StringUtil.replaceString(mpRow.get(COLUMN_NAME_6)));
excelRow.put("mobilePhone", StringUtil.replaceString(mpRow.get(COLUMN_NAME_7)));
excelRow.put("officeTel", StringUtil.replaceString(mpRow.get(COLUMN_NAME_8)));
excelRow.put("empNmEm", StringUtil.replaceString(mpRow.get(COLUMN_NAME_9)));
// 벨리데이션 체크 로직 추가
String rtnStr = ValidationCheckUtil.checkEmpExcelData(mpRow , userIdList
, COLUMN_NAME_1
, COLUMN_NAME_2
, COLUMN_NAME_3
, COLUMN_NAME_4
, COLUMN_NAME_5
, COLUMN_NAME_6
, COLUMN_NAME_7
, COLUMN_NAME_8
, COLUMN_NAME_9
);
if(rtnStr.equals("")) {
excelRow.put("xlsResultYn", "Y");
excelRow.put("xslResultNote", "");
} else {
excelRow.put("xlsResultYn", "N");
excelRow.put("xslResultNote", rtnStr);
}
excelRow.put("dmn", userSession.getDmn());
excelRow.put("userId", userSession.getUserId());
excelRow.put("crtTime", inserttime);
smc.update("mstEmp.saveExcelUploadMstEmp", excelRow);
intInsertCount++;
}
}
}
}
else
{
intReturnCode = ComnConst.RETURN_NO_DATA;
}
intReturnCode = ComnConst.RETURN_CODE_SUCCESS;
smc.executeBatch();
log.info("* EMP DATA INSERT END");
log.info("-------------------- RESULT --------------------");
log.info("* EMP DATA Insert Count = "+intInsertCount);
log.info("* Excel Row Count = "+intExcelRowCount);
log.info("* Return Code = "+intReturnCode);
log.info("------------------------------------------------");
}
catch(Exception ex)
{
intReturnCode = ComnConst.RETURN_UNKNOWN;
ex.printStackTrace();
log.info(ex.toString());
log.info(ex.getMessage());
}
finally
{
try
{
smc.endTransaction();
smc = null;
}
catch(SQLException e)
{
log.info("ERROR INFO : " + e.getMessage());
}
}
log.info("**saveSheetData() END");
return intReturnCode;
}
/**
* Get Excel Header Columns
* @param sheet
* @return arsColumns
*/
String[] getHeaderColumns(Sheet sheet, int headerIdx)
{
String[] arsColumns = null;
int intColIndex = 0;
Row clsRow = sheet.getRow(headerIdx);
while(clsRow.cellIterator().hasNext()
&& clsRow.getCell(intColIndex) != null
&& !"".equals(clsRow.getCell(intColIndex).toString().trim()))
{
intColIndex++;
}
arsColumns = new String[intColIndex];
String headerStr = "";
for(int intDataIndex = 0; intDataIndex < intColIndex; intDataIndex++)
{
headerStr = clsRow.getCell(intDataIndex).toString().trim();
// 한글 header값 영문 변경
for(int i=0; i < excelHeaderK.length; i++)
{
if(excelHeaderK[i].equals(headerStr))
{
headerStr = excelHeaderK[i]; //excelHeaderE[i];
break;
}
}
arsColumns[intDataIndex] = headerStr;
}
return arsColumns;
}
/**
* Get Excel Header Columns
* @param row
* @param columns
* @return Map<String, Object>
*/
Map<String, Object> rowToMap(Row row, String[] columns)
{
Map<String, Object> resultMap = null;
Cell cell;
int cellCnt;
Object value;
int blankCnt = 0;
if(row != null)
{
resultMap = new HashMap<>();
cellCnt = columns.length;
for(int i = 0; i < cellCnt; i++)
{
cell = row.getCell(i);
if(cell != null)
{
switch(cell.getCellType())
{
case Cell.CELL_TYPE_STRING:
value = (cell.getStringCellValue().replace("&", "&").replace("<", "<").replace(">", ">")).trim();
break;
case Cell.CELL_TYPE_NUMERIC:
if (DateUtil.isCellDateFormatted(cell))
{
Date date = cell.getDateCellValue();
value = new SimpleDateFormat("yyyyMMdd").format(date);
}
else
{
String fStr = (String.format("%.10f", cell.getNumericCellValue()));
String tStr = fStr.substring(fStr.indexOf('.') + 1, fStr.length());
if (Long.valueOf(tStr) > 0) {
value = fStr;
}
else {
value = fStr.substring(0, fStr.indexOf('.'));
}
}
break;
case Cell.CELL_TYPE_BOOLEAN:
value = cell.getBooleanCellValue() ? "1" : "0";
break;
case Cell.CELL_TYPE_FORMULA:
// 수식 셀 처리
switch (cell.getCachedFormulaResultType())
{
case Cell.CELL_TYPE_NUMERIC:
String fofStr = (String.format("%.10f", cell.getNumericCellValue()));
String fotStr = fofStr.substring(fofStr.indexOf('.') + 1, fofStr.length());
if (Long.valueOf(fotStr) > 0) {
value = fofStr;
}
else {
value = fofStr.substring(0, fofStr.indexOf('.'));
}
break;
case Cell.CELL_TYPE_STRING:
value = (cell.getStringCellValue().replace("&", "&").replace("<", "<").replace(">", ">")).trim();
break;
default:
value = cell.getCellFormula();
break;
}
break;
case Cell.CELL_TYPE_BLANK:
value = null;
blankCnt ++;
break;
case Cell.CELL_TYPE_ERROR:
value = (cell.getErrorCellValue() + "").trim();
break;
default:
value = "";
blankCnt ++;
break;
}
resultMap.put(columns[i], value);
}
else
{
resultMap.put(columns[i], "");
blankCnt++;
}
}
if(cellCnt == blankCnt)
{
resultMap = null;
}
}
return resultMap;
}
/**
* Upload 결과 값 Script 반환
*/
@Override
public String getResultScript()
{
StringBuilder buff = new StringBuilder();
buff.append(result.getOriFileNameList().get(0));
// String str = new String(result.getJsonString().getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1);
//
// if(!str.isEmpty())
// {
// buff.append("<script>");
// buff.append(String.format(" var result = %s;", str));
// buff.append(" parent.closeCurrentWindow(result);");
// buff.append("</script>");
// }
// else
// {
// buff.append("<script> var result = {};</script>");
// }
return buff.toString();
}
}
AbstractXLFileUploadService.java
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.StringWriter;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.dom4j.dom.DOMDocument;
import org.springframework.web.multipart.MultipartFile;
import ubsales.mdl.file.model.PathInfo;
import ubsales.mdl.file.service.AbstractFileUploadService;
public abstract class AbstractXLFileUploadService extends AbstractFileUploadService
{
private static final String MSG_XL_UPLOAD_FAIL = "Excel upload failed - %s";
private static final String MSG_FILE_DELETE_FAIL = "File delete failed";
@Override
protected int getNewFileId(MultipartFile file, PathInfo savePath)
{
int intResult = -1;
Workbook book;
File fileObj = null;
String strXML;
try
{
fileObj = new File(savePath.getSavePath());
}
catch(Exception ex)
{
log.info(ex.toString());
log.info(ex.getMessage());
}
if(fileObj != null && fileObj.exists())
{
try(FileInputStream fis = new FileInputStream(fileObj);)
{
log.info("Create book start");
book = checkExcelExt(fis, savePath.getOriginalName());
if(savePath.getOriginalName().toLowerCase().endsWith(".xls"))
{
book = new HSSFWorkbook(fis);
}
else if(savePath.getOriginalName().toLowerCase().endsWith(".xlsx"))
{
book = new XSSFWorkbook(fis);
}
log.info("Create book end");
if(book != null)
{
strXML = getSheetXML(book.getSheetAt(0));
log.info("get sheet end");
saveData(strXML);
log.info("data save complete");
}
intResult = 0;
}
catch(Exception ex)
{
log.info(String.format(MSG_XL_UPLOAD_FAIL, ex.toString()));
return intResult;
}
finally
{
try
{
Files.delete(Paths.get(savePath.getSavePath()));
}
catch(IOException e)
{
log.info(MSG_FILE_DELETE_FAIL);
}
}
}
return intResult;
}
Sheet getSheet(MultipartFile file, PathInfo savePath, int intSheetNum)
{
Sheet sheet = null;
Workbook book = null;
File fileObj = new File(savePath.getSavePath());
try(FileInputStream fis = new FileInputStream(fileObj);)
{
book = checkExcelExt(fis, savePath.getOriginalName());
if(book == null)
{
return sheet;
}
sheet = book.getSheetAt(intSheetNum);
}
catch(Exception ex)
{
log.info(String.format(MSG_XL_UPLOAD_FAIL, ex.toString()));
return sheet;
}
finally
{
try
{
Files.delete(Paths.get(savePath.getSavePath()));
}
catch(IOException e)
{
log.info("convertFile delete failed");
}
}
return sheet;
}
List<Sheet> getSheetMulti(MultipartFile file, PathInfo savePath)
{
List<Sheet> sheet = new ArrayList<>();
Workbook book = null;
File fileObj = new File(savePath.getSavePath());
try(FileInputStream fis = new FileInputStream(fileObj);)
{
book = checkExcelExt(fis, savePath.getOriginalName());
if(book == null) return sheet;
int intSheetNum = book.getNumberOfSheets();
if(intSheetNum > 0)
{
for(int i=0; i < intSheetNum; i++)
{
sheet.add(book.getSheetAt(i));
}
}
}
catch(Exception ex)
{
log.info(String.format(MSG_XL_UPLOAD_FAIL, ex.toString()));
return sheet;
}
finally
{
try
{
Files.delete(Paths.get(savePath.getSavePath()));
}
catch(IOException e)
{
log.info(MSG_FILE_DELETE_FAIL);
}
}
return sheet;
}
Workbook checkExcelExt(FileInputStream fis, String fileName)
{
Workbook book = null;
try
{
if(fileName.toLowerCase().endsWith(".xls")) book = new HSSFWorkbook(fis);
else if(fileName.toLowerCase().endsWith(".xlsx")) book = new XSSFWorkbook(fis);
}
catch(Exception ex)
{
log.info(String.format(MSG_XL_UPLOAD_FAIL, ex.toString()));
return book;
}
return book;
}
String convertDOM2XML(DOMDocument doc)
{
StringWriter sw = new StringWriter();
try
{
doc.write(sw);
return sw.getBuffer().toString().replaceAll("n|r", "");
}
catch(Exception ex)
{
return "";
}
}
protected abstract String getSheetXML(Sheet sheet);
protected abstract boolean saveData(String strXML);
}