일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
- 권한별메뉴만들기
- 유에이치스위트서울스퀘어
- MAC
- 유에이치스위트
- 데이터업로드
- 400에러관리
- springboot
- 사용자별메뉴
- 디너요리추천
- 재귀구문
- MySQL
- 오리지널팬케이스하우스 판교점
- jue
- 500에러관리
- csv업로드
- 판교테크원타워맛집
- menu만들기
- xcrunerror
- csv다운로드
- 오리지널팬케이스하우스
- 시청역놀곳
- 데이터베이스
- 바디캐싱
- 한남동중식
- 시청역숙소
- 스프링부트
- cachedbodyhttpservletrequest
- httpcode
- 컬럼타입변경
- 신사동이자카야
- Today
- Total
IT모저모
[SpringBoot] 데이터 엑셀 다운로드 (feat. 어노테이션만들기, 본문
안녕하세요 ~~
좀 지난 개발 이야기지만 끄적여보겠습니다 (다시 사용할 일이 생겨서..)
사내 근태프로그램을 만드는 중에 개인의 월 근태 기록을 엑셀로 다운로드 받아야하는 일이 생겼습니다.
저는 컴퓨터공학 전공을 하긴 했지만 학교다닐땐 진짜 못했걸랑요
시험을 위해서만 공부해왔던 저라...?
그래서 자바와 스프링부트를 혼자 독학했어요...
암튼 제 사담이었고요...
여기저기 구글링을 하며
이 기능에 제일 적합하면서 최대한 유연성있는 코드를 짜보자 해서 해당 코드를 만들게 됐어요
근태기록이라 함은
정해진 근무 스케줄이 있고 (저희는 유연근로제는 하지 않음) 정해진 식사시간, 연장근로시작, 휴일근로시간 등등 대체근무 등 엄청 많잖아요?
이를 에스원데이터와 연동하고 전자결재와 연동하기 전까지의 엑셀 데이터를 추출하는 작업을 했습니다.
전재결재 연동 후에도 엑셀 데이터 추출가능합니다 ^^
우선 ..
엑셀데이터를 출력하기 위해서는 정해진 틀이 필요하기 때문에 제가 손수 엑셀로 이 폼으로 나오면 좋겠다를 디자인 했어여
(저희는 기획자가 없어서 제가 혼자 다 해야함니다...)
파일은 yyyy년 MM월 이름.xlsx 으로 받아져야하고
아래의 디자인으로 파일이 받아져야합니다.,
매주 52시간 근로의 법이 있기 때문에 매주 총 근로시간도 계산해줘야하구요
실제 출근시각과 퇴근시각은 정산하는 시각과 다를 수 있기때문에 모든걸 고려해줘야합니다
아무튼... 저는 이 디자인 그리는 것도 정말 힘들었네요..
노란색 cell의 경우 출퇴근시각이 찍혀있지 않으면 노란색으로 표기했습니다!
근무일자, 근무요일~~~ 연장근무합계까지
cell backgroud가 정해져있는데 이는 어노테이션을 생성해줘서 dto에 어노테이션을 붙여 알아서 읽어오게끔했어요
아래 코드를 봐주세욧
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ExcelColumn {
String headerName() default "";
}
해당 어노테이션을 생성한 후에,
@Data
@Builder
@Getter @Setter
public class WorkHistoryDTO extends BaseTimeEntity {
private int id;
@ExcelColumn(headerName = "근무일자")
private String work_date;
}
위의 예시처럼 어노테이션을 지정하게 되면
어노테이션을 붙여놓은 컬럼만 읽어와 자동으로 cell value를 추가하게 됩니다
for (int i = 0; i < excelHeaderList.size(); i++) {
cell = row.createCell(i);
cell.setCellValue(excelHeaderList.get(i));
cell.setCellStyle(headerStyle);
}
요런식으로 하면 value를 추가하고 셀에 스타일을 추가하게 됩니다!
private Class<?> getClass(List<?> data) {
// List가 비어있지 않다면 List가 가지고 있는 모든 DTO는 같은 필드를 가지고 있으므로,
// 맨 마지막 DTO만 빼서 클래스 정보를 반환한다.
if(!CollectionUtils.isEmpty(data)) {
return data.get(data.size()-1).getClass();
} else {
throw new IllegalStateException("조회된 리스트가 비어 있습니다. 확인 후 다시 진행해주시기 바랍니다.");
}
}
private List<String> getHeaderName(Class<?> type) {
// 스트림으로 엑셀 헤더 이름들을 리스트로 반환
// 1. 매개변수로 전달된 클래스의 필드들을 배열로 받아, 스트림을 생성
// 2. @ExcelColumn 애너테이션이 붙은 필드만 수집
// 3. @ExcelColumn 애너테이션이 붙은 필드에서 애너테이션의 값을 매핑
// 4. LinkedList로 반환
List<String> excelHeaderNameList = Arrays.stream(type.getDeclaredFields())
.filter(s -> s.isAnnotationPresent(ExcelColumn.class))
.map(s -> s.getAnnotation(ExcelColumn.class).headerName())
.collect(Collectors.toCollection(LinkedList::new));
// 헤더의 이름을 담은 List가 비어있을 경우, 헤더 이름이 지정되지 않은 것이므로, 예외를 발생시킨다.
if(CollectionUtils.isEmpty(excelHeaderNameList)) {
throw new IllegalStateException("헤더 이름이 없습니다.");
}
return excelHeaderNameList;
}
해당 코드를 참고 하여 엑셀을 생성하는데 도움이 되셨으면 합니다~
물론 다음의 나에게두 ^^
감사합니닷
더 좋은 코드가 있으면 알려주세용
'Develop > SpringBoot' 카테고리의 다른 글
[SpringBoot] UserRole에 따라 Menu 접근 권한 나누기 (0) | 2024.12.17 |
---|---|
[SpringBoot] ResponseEntity로 Http 코드에 따라 응답데이터 반환하기 (1) | 2024.12.06 |
[SpringBoot] getReader 오류 발생 (해결) (2) | 2024.12.02 |
[Springboot] 400에러페이지 설정하기 (0) | 2023.07.05 |
[JSP] File Upload/Download 구현하기 (0) | 2023.05.23 |