반응형
목차
프로세스: 화면에서 엑셀 업로드 시 엑셀의 내용을 읽어서 테이블에 저장
의존성 추가(gradle)
//springBoot ver: 2.7.7
//poi 의존성 추가
implementation 'org.apache.poi:poi:5.1.0'
implementation 'org.apache.poi:poi-ooxml:5.1.0'
service
@Service
@Slf4j
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class ExcelService {
private final ExcelMapper excelMapper;
/**
* 엑셀업로드 화면
* @param mv
* @return
*/
@Override
public ModelAndView uploadForm(ModelAndView mv) {
mv.setViewName("upload");
return mv;
}
/**
* 엑셀 데이터 db 저장
* @return
*/
@Transactional
public ResponseEntity insertExcelInfo(MultipartFile file) {
//resultMap
Map<String, Object> resultMap = new HashMap<>();
try {
Workbook workbook = new XSSFWorkbook(file.getInputStream());
Sheet sheet = workbook.getSheetAt(0);
//엑셀 데이터 Vo
ExcelVo excelVo;
/**************** 엑셀 데이터 임시 테이블에 저장 ********************************************************/
int lastRowNum = sheet.getLastRowNum();
//1번 째 행은 header라서 2번 째 행부터 루프
for (int rowIndex = 1; rowIndex <= lastRowNum; rowIndex++) {
Row cells = sheet.getRow(rowIndex);
//Vo에 엑셀 데이터 세팅
excelVo = createExcelVoFromCells(cells);
//db 저장
excelMapper.insertExcelInfo(excelVo);
}
/********************************************************************************/
resultMap.put("code", ResultType.SUCCESS.getCode());
return new ResponseEntity<>(resultMap, HttpStatus.OK);
} catch (IOException ie) {
resultMap.put("code", ResultType.FAIL.getCode());
resultMap.put("message", "Failed to Process the Excel File: " + ie.getMessage());
return new ResponseEntity<>(resultMap, HttpStatus.BAD_REQUEST);
} catch (Exception e) {
resultMap.put("code", ResultType.FAIL.getCode());
resultMap.put("message", "Exception: " + e.getMessage());
return new ResponseEntity<>(resultMap, HttpStatus.BAD_REQUEST);
}
}
/**
* 엑셀파일 데이터 Vo에 세팅
* @param cells
* @param empId
* @return
*/
public ExcelVo createExcelVoFromCells(Row cells) {
ExcelVo excelVo = new ExcelVo();
excelVo.setEmpNo(getStringCellValue(cells, 0)); //사원번호
excelVo.setEmpNm(getStringCellValue(cells, 1)); //성명
excelVo.setDepartmentNm(getStringCellValue(cells, 2)); //부서
excelVo.setEmpEmail(getStringCellValue(cells, 3)); //이메일
excelVo.setEmpPosition(getStringCellValue(cells, 4)); //직급
//... 등등 기타 필드 세팅
return excelVo;
}
/**
* 엑셀에서 문자열 타입 값 가져옴
* @param row
* @param cellIndex
* @return
*/
public String getStringCellValue(Row row, int cellIndex) {
Cell cell = row.getCell(cellIndex);
return (cell != null) ? cell.getStringCellValue() : null;
}
}
RestController
@RestController
@Slf4j
@RequiredArgsConstructor
@RequestMapping(value = "/api/excel")
public class ExcelRestController {
private final ExcelService excelService;
/**
* 엑셀파일 db 저장
* @param file
* @return
*/
@PostMapping("/send")
public ResponseEntity insertExcelInfo(@RequestParam("file") MultipartFile file) {
return excelService.insertExcelInfo(file);
}
}
Controller
@Controller
@Slf4j
@RequiredArgsConstructor
@RequestMapping("/excel")
public class ExcelController {
private final ExcelService excelService;
/**
* 엑셀 업로드 화면
* @param mv
* @return
*/
@GetMapping(value = "/upload")
public ModelAndView uploadForm(ModelAndView mv) {
return excelService.uploadForm(mv);
}
}
Vo
@Data
//엑셀 데이터 Vo
public class ExcelVo {
private String empNo; //사원번호
private String empId; //아이디
private String empNm; //성명
private String departmentNm; //부서
private String empEmail; //이메일
private String empPosition; //직급
}
html(upload.html)
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorate="~{layout/default.html}"> <!-- 레이아웃 부분은 무시 -->
<!-- content(레이아웃 부분은 이 포스팅에선 무시) -->
<th:block layout:fragment="content">
<div class="contents" id="upload-form">
<!-- 메뉴 -->
<div class="section">
<input type="file" id="filefrm" class="btn-file" title="파일찾기" accept=".xlsx" @change="handleFileChange" />
<label for="filefrm">파일 첨부</label>
<button type="button" class="btn btn-normal" @click="upload">업로드</button>
</div>
</div>
</th:block>
<!-- Script -->
<script layout:fragment="script" th:inline="javascript" type="text/javascript">
//Vue.js 사용
new Vue({
//element id
el: '#upload-form',
//vue에서 관리할 데이터
data: {
/********* 데이터 저장 필드 *****************/
selectedFile: null, //첨부파일
},
//methods
methods: {
/**
* 첨부파일
*/
handleFileChange(e) {
this.selectedFile = e.target.files[0];
},
/**
* 첨부파일 업로드
*/
upload() {
if (confirm("업로드 하시겠습니까?")) {
const formData = new FormData();
const url = '/api/excel/send';
formData.append('file', this.selectedFile);
//post http request
axios.post(url, formData, {
headers: {'Content-Type': 'multipart/form-data'}
})
.then(function (response) {
console.log(response.data.code);
if (response.data.code === '1') {
alert("등록 되었습니다.");
} else {
console.log(response.data.message);
alert("등록 실패했습니다.");
}
}.bind(this))
.catch(function (error) {
alert("등록 실패했습니다.");
console.log(error);
});
}
},
},
});
</script>
</html>
결과(보안상 개인정보는 가렸음)
실제 프로젝트 소스에서 편집한 코드라 메소드명이나 코드상 어색한 부분이 있을 수도 있음
개인 스터디 기록을 메모하는 공간이라 틀린점이 있을 수 있습니다.
틀린 점 있을 경우 댓글 부탁드립니다.
반응형
'IT > development' 카테고리의 다른 글
[JavaScript] htmlToPdf convert(feat. html2pdf) (84) | 2023.08.26 |
---|---|
[Git] Git Branching Strategy(feat. 브랜치 전략) (66) | 2023.08.24 |
[Java] 가변인자 사용(feat. String ... str) (37) | 2023.08.22 |
[springBoot] daum SMTP 메일 발송 (43) | 2023.08.22 |
[github] github 웹 vs code 사용 (0) | 2023.08.17 |