map) {
- data = map;
- return this;
- }
-
- /**엑셀 파일에 저장할 데이터들을 설정한다.
- * @param key 데이터 키
- * @param obj 데이터
- * @return 현재 XLS
- */
- public JXLS setData(String key, Object obj) {
- if (data == null) {
- data = new LinkedHashMap<>();
- }
- data.put(key, obj);
- return this;
- }
-
- @Override
- public void write(OutputStream out) {
- ctx = new Context();
- getData().forEach(ctx::putVar);
-
- try (InputStream input = loadTemplate();) {
- JxlsHelper.getInstance().processTemplate(input, out, ctx);
- } catch (Exception e) {
- throw runtimeException(e);
- }
- }
-}
\ No newline at end of file
diff --git a/src/main/java/cokr/xit/base/file/xls/XLS.java b/src/main/java/cokr/xit/base/file/xls/XLS.java
deleted file mode 100644
index a11a80b..0000000
--- a/src/main/java/cokr/xit/base/file/xls/XLS.java
+++ /dev/null
@@ -1,125 +0,0 @@
-package cokr.xit.base.file.xls;
-
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-
-import org.springframework.core.io.ClassPathResource;
-
-import cokr.xit.foundation.AbstractComponent;
-
-/**엑셀 스프레드시트의 읽기나 쓰기를 돕는 유틸리티
- * @author mjkhan
- */
-public abstract class XLS extends AbstractComponent {
- /**엑셀 파일(*.xlsx)의 mime type */
- public static final String MIME_TYPE = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
-
- private String
- template,
- filename;
-
- /**템플릿 파일경로를 반환한다.
- * @return 템플릿 파일경로
- */
- public String getTemplate() {
- return template;
- }
-
- protected InputStream loadTemplate() throws Exception {
- if (isEmpty(template))
- return null;
- return new ClassPathResource(template).getInputStream();
- }
-
- /**템플릿 파일경로를 설정한다.
- * @param template 템플릿 파일경로
- * @return 현재 XLS
- */
- public XLS setTemplate(String template) {
- this.template = template;
- return this;
- }
-
- /**저장할 파일이름을 반환한다.
- * 디폴트는 'yyyyMMdd-HHmmss.xlsx'
- * @return 저장할 파일이름
- */
- public String getFilename() {
- return ifEmpty(filename, () -> new SimpleDateFormat("yyyyMMdd-HHmmss").format(new Date()) + ".xlsx");
- }
-
- /**저장할 파일이름을 설정한다.
- * 디폴트는 'yyyyMMdd-HHmmss.xlsx'
- * @param filename 저장할 파일이름
- * @return 현재 XLS
- */
- public XLS setFilename(String filename) {
- this.filename = filename;
- return this;
- }
-
- /**설정된 데이터를 엑셀 파일 포맷으로 out에 저장한다.
- * @param out OutputStream
- */
- public abstract void write(OutputStream out);
-
- /**yyyyMMdd, 또는 yyMMdd 포맷의 문자열을 yyyy-MM-dd 포맷으로 변환하여 반환한다.
- * @param obj yyyyMMdd, 또는 yyMMdd 포맷의 문자열
- * @return yyyy-MM-dd 포맷 문자열
- */
- public final String str2date(Object obj) {
- if (isEmpty(obj)) return "";
-
- String str = obj.toString();
- int length = str.length(),
- pos = length - 2;
-
- String
- day = str.substring(pos),
- month = str.substring(pos = pos - 2, pos + 2),
- year = str.substring(0, pos);
- return String.format("%s-%s-%s", year, month, day);
- }
-
- /**HHmmss 포맷의 문자열을 HH:mm:ss 포맷으로 변환하여 반환한다.
- * @param obj HHmmss 포맷의 문자열
- * @return HH:mm:ss 포맷 문자열
- */
- public final String str2time(Object obj) {
- if (isEmpty(obj)) return "";
-
- String str = obj.toString();
- int length = str.length(),
- pos = length - 2;
-
- String
- ss = str.substring(pos),
- mm = str.substring(pos = pos - 2, pos + 2),
- hh = str.substring(0, pos);
- return String.format("%s:%s:%s", hh, mm, ss);
- }
-
- /**yyyyMMddHHmmss, 또는 yyMMddHHmmss 포맷의 문자열을 yyyy-MM-dd HH:mm:ss 포맷으로 변환하여 반환한다.
- * @param obj yyyyMMddHHmmss, 또는 yyMMddHHmmss 포맷의 문자열
- * @return yyyy-MM-dd HH:mm:ss 포맷 문자열
- */
- public final String str2datetime(Object obj) {
- if (isEmpty(obj)) return "";
-
- String str = obj.toString();
- int length = str.length(),
- pos = length - 6;
-
- try {
- String
- date = str.substring(0, pos),
- time = str.substring(pos);
-
- return str2date(date) + " " + str2time(time);
- } catch (Exception e) {
- return str;
- }
- }
-}
\ No newline at end of file
diff --git a/src/main/java/cokr/xit/base/file/xls/XLSWriter.java b/src/main/java/cokr/xit/base/file/xls/XLSWriter.java
deleted file mode 100644
index ba9b0c2..0000000
--- a/src/main/java/cokr/xit/base/file/xls/XLSWriter.java
+++ /dev/null
@@ -1,1038 +0,0 @@
-package cokr.xit.base.file.xls;
-
-import java.io.FileInputStream;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Date;
-import java.util.List;
-import java.util.Map;
-import java.util.function.Consumer;
-import java.util.function.Function;
-import java.util.function.Supplier;
-import java.util.stream.Stream;
-
-import org.apache.poi.ooxml.POIXMLDocumentPart.RelationPart;
-import org.apache.poi.ss.usermodel.BorderStyle;
-import org.apache.poi.ss.usermodel.CellStyle;
-import org.apache.poi.ss.usermodel.ClientAnchor;
-import org.apache.poi.ss.usermodel.CreationHelper;
-import org.apache.poi.ss.usermodel.FillPatternType;
-import org.apache.poi.ss.usermodel.Font;
-import org.apache.poi.ss.usermodel.HorizontalAlignment;
-import org.apache.poi.ss.usermodel.VerticalAlignment;
-import org.apache.poi.ss.util.CellRangeAddress;
-import org.apache.poi.xssf.streaming.SXSSFCell;
-import org.apache.poi.xssf.streaming.SXSSFDrawing;
-import org.apache.poi.xssf.streaming.SXSSFRow;
-import org.apache.poi.xssf.streaming.SXSSFSheet;
-import org.apache.poi.xssf.streaming.SXSSFWorkbook;
-import org.apache.poi.xssf.usermodel.XSSFComment;
-import org.apache.poi.xssf.usermodel.XSSFPictureData;
-import org.apache.poi.xssf.usermodel.XSSFRelation;
-import org.apache.poi.xssf.usermodel.XSSFVMLDrawing;
-import org.apache.poi.xssf.usermodel.XSSFWorkbook;
-import org.openxmlformats.schemas.officeDocument.x2006.sharedTypes.STTrueFalse;
-import org.springframework.util.FileCopyUtils;
-
-import com.fasterxml.jackson.core.type.TypeReference;
-import com.microsoft.schemas.vml.CTFill;
-import com.microsoft.schemas.vml.CTShape;
-import com.microsoft.schemas.vml.STFillType;
-
-/**대용량 데이터를 엑셀 파일로 저장하는 유틸리티.
- * XLSWriter는 엑셀 템플릿 파일을 사용하도록 할 수 있다.
- * XLSWriter xlsx = new XLSWriter().setTemplate("...");
- * XLSWriter가 데이터를 저장한 엑셀 파일을 다운로드할 때 사용할 이름을 지정할 수 있다.
- * XLSWriter xlsx = new XLSWriter()
- * .setTemplate("...")
- * .setFilename("...");
- * XLSWriter가 데이터를 엑셀로 저장하려면 워크시트와 작업셀을 지정해야 한다.
- * xlsx.worksheet(0) //워크시트 설정
- * .row(0) //첫번째 행
- * .col(0); //첫번째 열의 셀을 작업셀로 설정
- * 엑셀로 저장할 데이터를 준비한다.
- * List<DataObject> dataset = ...;
- * XLSWriter에 데이터를 설정한다.
- * xlsx.values(dataset);
- * 위 코드는 dataset의 모든 필드값들을 설정한다.
- * dataset의 특정 필드의 값들을 원하는 순서대로 설정하려면 해당 필드들의 이름을 순서대로 나열한다.
- * xlsx.values(dataset, "RCPT_ID", "RCPT_DT", "PAYER_NM", "RCPT_AMT");
- * dataset의 특정 필드의 값들에 스타일을 적용하려면 {@link Formatter}을 표시한다.
- * CellStyle
- * datetime = xlsx.yyyy_mm_dd_hh_mm_ss(),
- * numeric = xlsx.n_nn0();
- * xlsx.values(dataset, "RCPT_ID", xlsx.style("RCPT_DT", datetime), "PAYER_NM", xlsx.style("RCPT_AMT", numeric));
- * @author mjkhan
- */
-public class XLSWriter extends XLS {
- private int rowAccessWindowSize = 128;
- private SXSSFWorkbook workbook;
- private SXSSFSheet worksheet;
- private SXSSFRow row;
- private SXSSFCell cell;
-
- @Override
- public XLSWriter setTemplate(String template) {
- super.setTemplate(template);
- return this;
- }
-
- @Override
- public XLSWriter setFilename(String filename) {
- super.setFilename(filename);
- return this;
- }
-
- @Override
- public void write(OutputStream out) {
- try {
- workbook.write(out);
- workbook.dispose();
- } catch (Exception e) {
- throw runtimeException(e);
- } finally {
- clear();
- }
- }
-
- public SXSSFWorkbook workbook() {
- if (workbook != null)
- return workbook;
-
- try {
- InputStream template = loadTemplate();
- if (template != null) {
- XSSFWorkbook xssf = new XSSFWorkbook(template);
- workbook = new SXSSFWorkbook(xssf, rowAccessWindowSize);
- } else {
- workbook = new SXSSFWorkbook(rowAccessWindowSize);
- }
- workbook.setCompressTempFiles(true);
- return workbook;
- } catch (Exception e) {
- throw runtimeException(e);
- }
- }
-
- /**지정한 인덱스의 워크시트를 반환한다.
- * 워크시트가 없으면 해당 인덱스로 워크시트를 생성 후 반환한다.
- * @param index 워크시트 인덱스(0부터 시작)
- * @return 워크시트
- */
- public XLSWriter worksheet(int index) {
- try {
- worksheet = workbook().getSheetAt(index);
- } catch (Exception e) {
- worksheet = workbook().createSheet();
- }
- worksheet.setRandomAccessWindowSize(rowAccessWindowSize);
- return this;
- }
-
- /**지정한 이름의 워크시트를 반환한다.
- * 워크시트가 없으면 해당 이름의 워크시트를 생성 후 반환한다.
- * @param name 워크시트 이름
- * @return 워크시트
- */
- public XLSWriter worksheet(String name) {
- try {
- SXSSFWorkbook wb = workbook();
- worksheet = ifEmpty(wb.getSheet(name), () -> wb.createSheet(name));
- worksheet.setRandomAccessWindowSize(rowAccessWindowSize);
- return this;
- } catch (Exception e) {
- throw runtimeException(e);
- }
- }
-
- /**지정한 인덱스의 행(row)을 작업행으로 설정한다.
- * 해당 행이 없으면 생성 후 작업행으로 설정한다.
- * @param index 행 인덱스(0부터 시작)
- * @return 현재 XLSWriter
- */
- public XLSWriter row(int index) {
- row = ifEmpty(worksheet.getRow(index), () -> worksheet.createRow(index));
- return this;
- }
-
- /**현재 작업행의 지정한 인덱스의 열(column)을 작업셀로 설정한다.
- * 해당 셀이 없으면 생성 후 작업셀로 설정한다.
- * @param index 열 인덱스(0부터 시작)
- * @return 현재 XLSWriter
- */
- public XLSWriter col(int index) {
- cell = ifEmpty(row.getCell(index), () -> row.createCell(index));
- return this;
- }
-
- /**지정한 행과 열 인덱스의 셀을 작업셀로 설정한다.
- * @param row 행 인덱스
- * @param col 열 인덱스
- * @return 현재 XLSWriter
- */
- public XLSWriter cell(int row, int col) {
- return row(row).col(col);
- }
-
- /**지정한 범위의 셀들을 병합한다.
- * @param firstRow 시작행 인덱스
- * @param lastRow 끝행 인덱스
- * @param firstCol 시작열 인덱스
- * @param lastCol 끝열 인덱스
- * @return 현재 XLSWriter
- */
- public XLSWriter merge(int firstRow, int lastRow, int firstCol, int lastCol) {
- worksheet.addMergedRegion(new CellRangeAddress(firstRow, lastRow, firstCol, lastCol));
- return this;
- }
-
- /**현재 행의 지정한 열의 셀들을 병합한다.
- * @param firstCol 시작열 인덱스
- * @param lastCol 끝열 인덱스
- * @return 현재 XLSWriter
- */
- public XLSWriter merge(int firstCol, int lastCol) {
- int index = row.getRowNum();
- return merge(index, index, firstCol, lastCol);
- }
-
- /**지정한 값을 현재 작업셀에 설정하고 스타일을 적용한다.
- * @param val 설정값
- * @param style 적용할 스타일(CellStyle, Styler, 또는 KeyStyle)
- * @return 현재 XLSWriter
- */
- public XLSWriter value(Object val, Object style) {
- if (!isEmpty(val)) {
- if (val instanceof String) {
- cell.setCellValue((String)val);
- } else if (val instanceof Number) {
- Number number = (Number)val;
- cell.setCellValue(number.doubleValue());
- } else if (val instanceof Date) {
- cell.setCellValue((Date)val);
- } else if (val instanceof Boolean) {
- Boolean b = (Boolean)val;
- cell.setCellValue(b.booleanValue());
- } else
- throw new IllegalArgumentException(val.getClass().getName() + ": " + val);
- }
- setCellStyle(style);
-
- return this;
- }
-
- /**지정한 값을 현재 작업셀에 설정한다.
- * @param val 설정값
- * @return 현재 XLSWriter
- */
- public XLSWriter value(Object val) {
- return value(val, null);
- }
-
- /**지정한 값들을 현재 작업셀부터 행으로 순서대로 설정한다.
- * 값이 설정된 셀에 스타일을 적용하려면 해당값의 바로 뒤에 스타일을 지정한다.
- * 다음은 사용례다.
- * XLSWriter xlsx = new XLSWriter()
- * .setTemplate("...") // 템플릿 사용 시 지정
- * .setFilename("...") // 다운로드 시 파일이름 지정
- * .worksheet(0) // 워크시트 지정
- * .cell(0, 0) // 작업셀 지정
- * .rowValues(List.of("하나", 10000, new Date()));
- * 두번째 값에는 숫자포맷을, 세번째 값에는 날짜포맷을 지정하려면 다음과 같이 한다.
- * CellStyle numeric = xlsx.n_nn0(); //{@link #cellStyle(Styler)} 참고
- * CellStyle datetime = xlsx.yyyy_mm_dd_hh_mm_ss();
- * ...
- * xlsx.rowValues(List.of("하나", 10000, numeric, new Date(), datetime));
- * @param vals 설정값(스타일 포함)
- * @return 현재 XLSWriter
- */
- public XLSWriter rowValues(Iterable> vals) {
- if (!isEmpty(vals)) {
- int start = cell.getColumnIndex(),
- x = start;
- for (Object val: vals) {
- if (val instanceof Styler) {
- setCellStyle(val);
- } else if (val instanceof CellStyle) {
- setCellStyle(val);
- } else if (val instanceof Formatter) {
- setCellStyle(val);
- } else if (val instanceof Runnable) {
- ((Runnable)val).run();
- } else {
- col(x).value(val);
- ++x;
- }
- }
- col(start);
- }
- return this;
- }
-
- private void setCellStyle(Object obj) {
- Styler styler = null;
- CellStyle style = null;
-
- if (obj instanceof CellStyle) {
- style = (CellStyle)obj;
- } else if (obj instanceof Styler) {
- styler = (Styler)obj;
- } else if (obj instanceof Formatter) {
- Formatter formatter = (Formatter)obj;
- styler = formatter.styler;
- style = formatter.style;
- }
-
- if (styler != null) {
- style = cellStyle(styler);
- if (styler.width != null) {
- if (styler.width < 256)
- worksheet.setColumnWidth(cell.getColumnIndex(), styler.width * 256);
- else
- worksheet.autoSizeColumn(cell.getColumnIndex());
- }
- if (styler.height != null)
- row.setHeight(styler.height);
- }
- if (style != null)
- cell.setCellStyle(style);
- }
-
- private Iterable> vals(Map, ?> map, Object[] keysAndStyles) {
- if (isEmpty(map))
- return Collections.emptyList();
-
- if (isEmpty(keysAndStyles))
- return map.values();
-
- ArrayList vals = new ArrayList<>();
- for (Object obj: keysAndStyles) {
- if (obj instanceof Formatter) {
- Formatter formatter = (Formatter)obj;
- Object val = null;
- if (formatter.key != null) {
- val = map.get(formatter.key);
- } else if (formatter.convert != null){
- val = formatter.convert.apply(map);
- }
- vals.add(val);
- if (formatter.onCell != null)
- vals.add(formatter.onCell.apply(map));
-
- Styler styler = formatter.styler;
- CellStyle style = formatter.style;
- if (styler != null)
- style = cellStyle(styler);
- if (style != null)
- vals.add(style);
- } else {
- vals.add(map.get(obj));
- }
- }
- return vals;
- }
-
- /**지정한 map의 값들을 현재 작업셀부터 행으로 설정한다.
- * 설정할 값과 순서를 정하려면 해당 값들의 키를 지정한다.
- * 값이 설정된 셀에 스타일을 적용하려면 {@link Formatter}로 키와 스타일을 지정한다.
- * 다음은 map의 모든 값들을 설정하는 예다.
- * DataObject rec = new DataObject().set("NO", 1).set("PAYER", "홍길동").set("RCPT_AMT", 10000).set("RCPT_DT", new Date());
- * XLSWriter xlsx = new XLSWriter()
- * .setTemplate("...") // 템플릿 사용 시 지정
- * .setFilename("...") // 다운로드 시 파일이름 지정
- * .worksheet(0) // 워크시트 지정
- * .cell(0, 0) // 작업셀 지정
- * .rowValues(rec);
- * 설정할 값들을 지정하려면 다음과 같이 한다.
- * xlsx.rowValues(rec, "PAYER", "RCPT_AMT", "RCPT_DT");
- * RCPT_AMT, RCPT_DT에 숫자포맷과 날짜포맷을 적용하려면 다음과 같이 한다.
- * CellStyle numeric = xlsx.n_nn0(); //{@link #cellStyle(Styler)} 참고
- * CellStyle datetime = xlsx.yyyy_mm_dd_hh_mm_ss();
- * ...
- * xlsx.rowValues(rec, "PAYER", xlsx.keyStyle("RCPT_AMT", numeric), xlsx.keyStyle("RCPT_DT", datetime));
- * @param map 맵
- * @param keysAndStyles 셀에 설정할 값들의 키, 또는 {@link Formatter 키와 스타일}
- * @return 현재 XLSWriter
- */
- public XLSWriter rowValues(Map, ?> map, Object... keysAndStyles) {
- return rowValues(vals(map, keysAndStyles));
- }
-
- /**지정한 데이터셋의 값들을 현재 작업셀부터 행과 열로 설정한다.
- * 설정할 값과 순서를 정하려면 해당 값들의 키를 지정한다.
- * 값이 설정된 셀에 스타일을 적용하려면 {@link Formatter}로 키와 스타일을 지정한다.
- * 다음은 데이터셋의 모든 값들을 설정하는 예다.
- * List<DataObject> dataset = ...;
- * XLSWriter xlsx = new XLSWriter()
- * .setTemplate("...") // 템플릿 사용 시 지정
- * .setFilename("...") // 다운로드 시 파일이름 지정
- * .worksheet(0) // 워크시트 지정
- * .cell(0, 0) // 작업셀 지정
- * .rowValues(dataset);
- * 설정할 값들을 지정하려면 다음과 같이 한다.
- * xlsx.rowValues(dataset, "PAYER", "RCPT_AMT", "RCPT_DT");
- * RCPT_AMT, RCPT_DT에 숫자포맷과 날짜포맷을 적용하려면 다음과 같이 한다.
- * CellStyle numeric = xlsx.n_nn0(); //{@link #cellStyle(Styler)} 참고
- * CellStyle datetime = xlsx.yyyy_mm_dd_hh_mm_ss();
- * ...
- * xlsx.rowValues(dataset, "PAYER", xlsx.style("RCPT_AMT", numeric), xlsx.style("RCPT_DT", datetime));
- * @param dataset 데이터셋
- * @param keysAndStyles 셀에 설정할 값들의 키, 또는 {@link Formatter 키와 스타일}
- * @return 현재 XLSWriter
- */
- public XLSWriter values(Iterable extends Map, ?>> dataset, Object... keysAndStyles) {
- if (!isEmpty(dataset)) {
- int c = cell.getColumnIndex(),
- r = cell.getRowIndex();
- Object[] kas = Stream.of(keysAndStyles)
- .map(obj -> !(obj instanceof Styler) ? obj : cellStyle((Styler)obj))
- .toList()
- .toArray();
-
- for (Map, ?> rec: dataset) {
- cell(r, c);
- rowValues(rec, kas);
- ++r;
- }
- }
- return this;
- }
-
- /**스타일 정보에서 셀스타일을 생성하여 반환한다.
- * @param styler 스타일 정보
- * @return 셀스타일
- */
- public CellStyle cellStyle(Styler styler) {
- if (styler == null)
- return null;
-
- CellStyle cellStyle = workbook.createCellStyle();
- styler.set(cellStyle);
- if (styler.dataFormat != null) {
- cellStyle.setDataFormat(workbook.createDataFormat().getFormat(styler.dataFormat));
- }
- return cellStyle;
- }
-
- /**지정한 키와 셀스타일을 연결한 KeyStyle을 반환한다.
- * @param key 키
- * @param style 셀스타일
- * @return KeyStyle
- */
- public Formatter formatter(Object key) {
- return new Formatter().key(key);
- }
-
- /**데이터 포맷 function을 설정한다.
- * @param func 데이터 포맷 function
- * @return Formatter
- */
- public Formatter format(Function, Object> func) {
- return formatter(null).format(func);
- }
-
- /**지정한 데이터 키의 스타일(CellStyle, 또는 Styler)를 설정한다.
- * @param key 데이터 키
- * @param style 스타일(CellStyle, 또는 Styler)
- * @return Formatter
- */
- public Formatter style(Object key, Object style) {
- Formatter fmt = formatter(key);
- if (style instanceof CellStyle)
- fmt.style((CellStyle)style);
- else if (style instanceof Styler)
- fmt.styler((Styler)style);
- return fmt;
- }
-
- /**현재 XLSWriter의 내부상태를 초기화하여 반환한다.
- * @return 현재 XLSWriter
- */
- public XLSWriter clear() {
- cell = null;
- row = null;
- worksheet = null;
- workbook = null;
- rowAccessWindowSize = 128;
- return this;
- }
-
- /**숫자 스타일(오른쪽 정렬, 천단위 구분)을 반환한다.
- * @return 숫자 스타일(오른쪽 정렬, 천단위 구분)
- */
- public CellStyle n_nn0() {
- return cellStyle(new Styler().alignment(HorizontalAlignment.RIGHT).dataFormat("#,##0"));
- }
-
- /**숫자 스타일(오른쪽 정렬, 천단위 구분, 소수점 2자리 표기)을 반환한다.
- * @return 숫자 스타일(오른쪽 정렬, 천단위 구분, 소수점 2자리 표기)
- */
- public CellStyle n_nn0_2() {
- return cellStyle(new Styler().dataFormat("#,###.00").merge(Styler.RIGHT));
- }
-
- /**날짜 포맷(yyyy-MM-dd HH:mm:ss)의 셀스타일을 반환한다.
- * @return 날짜 포맷(yyyy-MM-dd HH:mm:ss)의 셀스타일
- */
- public CellStyle yyyy_mm_dd_hh_mm_ss() {
- return cellStyle(new Styler().dataFormat("yyyy-MM-dd HH:mm:ss").merge(Styler.CENTER));
- }
-
- /**날짜 포맷(yyyy-MM-dd)의 셀스타일을 반환한다.
- * @return 날짜 포맷(yyyy-MM-dd)의 셀스타일
- */
- public CellStyle yyyy_mm_dd() {
- return cellStyle(new Styler().dataFormat("yyyy-MM-dd").merge(Styler.CENTER));
- }
-
- /**시간 포맷(HH:mm:ss)의 셀스타일을 반환한다.
- * @return 시간 포맷(HH:mm:ss)의 셀스타일
- */
- public CellStyle hh_mm_ss() {
- return cellStyle(new Styler().dataFormat("HH:mm:ss").merge(Styler.CENTER));
- }
-
- /**셀스타일 정보. {@link #set(CellStyle) CellStyle을 설정}하는데 사용.
- * @author mjkhan
- */
- public static class Styler {
- /** 빈 스타일 */
- public static final Styler NONE = new Styler().seal();
- /** 좌측 정렬 */
- public static final Styler LEFT = new Styler().alignment(HorizontalAlignment.LEFT).seal();
- /** 가운데 정렬 */
- public static final Styler CENTER = new Styler().alignment(HorizontalAlignment.CENTER).seal();
- /** 우측 정렬 */
- public static final Styler RIGHT = new Styler().alignment(HorizontalAlignment.RIGHT).seal();
-
- private boolean sealed;
-
- private Integer width;
- private Short height;
-
- private HorizontalAlignment horizontalAlignment;
- private VerticalAlignment verticalAlignment;
-
- private Border
- borderTop,
- borderRight,
- borderBottom,
- borderLeft;
-
- private Short foregroundColor;
-
- private Font font;
- private String dataFormat;
-
- /**열의 폭을 설정한다.
- * @param chars 열의 폭. 한번에 보여지는 문자수
- * @return 현재 Styler
- */
- public Styler width(int chars) {
- this.width = chars;
- return this;
- }
-
- /**행의 높이를 설정한다.
- * @param height 행의 높이
- * @return 현재 Styler
- */
- public Styler height(short height) {
- this.height = height;
- return this;
- }
-
- /**가로정렬을 설정한다.
- * @param alignment 가로정렬
- * @return 현재 Styler
- */
- public Styler alignment(HorizontalAlignment alignment) {
- ensureNotSealed();
- horizontalAlignment = alignment;
- return this;
- }
-
- /**세로정렬을 설정한다.
- * @param alignment 세로정렬
- * @return 현재 Styler
- */
- public Styler alignment(VerticalAlignment alignment) {
- ensureNotSealed();
- verticalAlignment = alignment;
- return this;
- }
-
- /**윗쪽 테두리 스타일을 설정한다.
- * @param border 테두리 스타일 정보
- * @return 현재 Styler
- */
- public Styler borderTop(Border border) {
- ensureNotSealed();
- borderTop = border;
- return this;
- }
-
- /**오른쪽 테두리 스타일을 설정한다.
- * @param border 테두리 스타일 정보
- * @return 현재 Styler
- */
- public Styler borderRight(Border border) {
- ensureNotSealed();
- borderRight = border;
- return this;
- }
-
- /**아래쪽 테두리 스타일을 설정한다.
- * @param border 테두리 스타일 정보
- * @return 현재 Styler
- */
- public Styler borderBottom(Border border) {
- ensureNotSealed();
- borderBottom = border;
- return this;
- }
-
- /**왼쪽 테두리 스타일을 설정한다.
- * @param border 테두리 스타일 정보
- * @return 현재 Styler
- */
- public Styler borderLeft(Border border) {
- ensureNotSealed();
- borderLeft = border;
- return this;
- }
-
- /**배경색을 설정한다.
- * @param color
- * @return 현재 Styler
- */
- public Styler foregroundColor(short color) {
- ensureNotSealed();
- foregroundColor = color;
- return this;
- }
-
- /**폰트를 설정한다.
- * @param font 폰트
- * @return 현재 Styler
- */
- public Styler font(Font font) {
- ensureNotSealed();
- this.font = font;
- return this;
- }
-
- /**데이터 포맷을 설정한다.
- * @param dataFormat 데이터 포맷
- * @return 현재 Styler
- */
- public Styler dataFormat(String dataFormat) {
- ensureNotSealed();
- this.dataFormat = dataFormat;
- return this;
- }
-
- /**셀스타일에 현재 스타일 정보를 설정한다.
- * @param style 셀스타일
- */
- public void set(CellStyle style) {
- if (style == null) return;
-
- if (horizontalAlignment != null)
- style.setAlignment(horizontalAlignment);
- if (verticalAlignment != null)
- style.setVerticalAlignment(verticalAlignment);
-
- if (borderTop != null) {
- if (borderTop.style != null)
- style.setBorderTop(borderTop.style);
- if (borderTop.color != null)
- style.setTopBorderColor(borderTop.color);
- }
- if (borderRight != null) {
- if (borderRight.style != null)
- style.setBorderRight(borderRight.style);
- if (borderRight.color != null)
- style.setRightBorderColor(borderRight.color);
- }
- if (borderBottom != null) {
- if (borderBottom.style != null)
- style.setBorderBottom(borderBottom.style);
- if (borderBottom.color != null)
- style.setBottomBorderColor(borderBottom.color);
- }
- if (borderLeft != null) {
- if (borderLeft.style != null)
- style.setBorderLeft(borderLeft.style);
- if (borderLeft.color != null)
- style.setLeftBorderColor(borderLeft.color);
- }
- if (foregroundColor != null) {
- style.setFillForegroundColor(foregroundColor);
- style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
- }
-
- if (font != null)
- style.setFont(font);
- }
-
- public Styler configure(Consumer configurer) {
- ensureNotSealed();
- if (configurer != null)
- configurer.accept(this);
- return this;
- }
-
- public Styler merge(Styler other) {
- Styler copy = new Styler();
-
- copy.width = this.width;
- copy.height = this.height;
-
- copy.horizontalAlignment = this.horizontalAlignment;
- copy.verticalAlignment = this.verticalAlignment;
-
- copy.borderTop = this.borderTop;
- copy.borderRight = this.borderRight;
- copy.borderBottom = this.borderBottom;
- copy.borderLeft = this.borderLeft;
-
- copy.foregroundColor = this.foregroundColor;
- copy.font = this.font;
- copy.dataFormat = this.dataFormat;
-
- if (other.width != null)
- copy.width = other.width;
- if (other.height != null)
- copy.height = other.height;
-
- if (other.horizontalAlignment != null)
- copy.horizontalAlignment = other.horizontalAlignment;
- if (other.verticalAlignment != null)
- copy.verticalAlignment = other.verticalAlignment;
-
- if (other.borderTop != null)
- copy.borderTop = other.borderTop;
- if (other.borderRight != null)
- copy.borderRight = other.borderRight;
- if (other.borderBottom != null)
- copy.borderBottom = other.borderBottom;
- if (other.borderLeft != null)
- copy.borderLeft = other.borderLeft;
-
- if (other.foregroundColor != null)
- copy.foregroundColor = other.foregroundColor;
- if (other.font != null)
- copy.font = other.font;
- if (other.dataFormat != null)
- copy.dataFormat = other.dataFormat;
-
- return copy;
- }
-
- private Styler seal() {
- sealed = true;
- return this;
- }
-
- private void ensureNotSealed() {
- if (sealed)
- throw new RuntimeException("The Style is sealed and unmodifieable");
- }
- }
-
- /**테두리 스타일 정보
- * @author mjkhan
- */
- public static class Border {
- private BorderStyle style;
- private Short color;
-
- /**테두리 스타일 정보를 설정한다.
- * @param style 테두리 스타일 정보
- * @return 현재 테두리 스타일 정보
- */
- public Border style(BorderStyle style) {
- this.style = style;
- return this;
- }
-
- /**테두리 색깔을 설정한다.
- * @param color 테두리 색깔
- * @return 현재 테두리 스타일 정보
- */
- public Border color(short color) {
- this.color = color;
- return this;
- }
- }
-
- /**데이터 포맷, 셀스타일을 특정키와 연결하는 정보
- * @author mjkhan
- */
- public static class Formatter {
- private Object key;
-
- private Function, Object> convert;
-
- private CellStyle style;
- private Styler styler;
-
- private Function, Runnable> onCell;
-
- /**데이터 키를 설정한다.
- * @param key 데이터 키
- * @return 현재 Formatter
- */
- public Formatter key(Object key) {
- this.key = key;
- return this;
- }
-
- /**데이터 포맷 function을 설정한다.
- * @param func 데이터 포맷 설정
- * @return 현재 Formatter
- */
- public Formatter format(Function, Object> func) {
- convert = func;
- return this;
- }
-
- /**셀스타일을 설정한다.
- * @param style 셀스타일
- * @return 현재 Formatter
- */
- public Formatter style(CellStyle style) {
- this.style = style;
- return this;
- }
-
- /**스타일러를 설정한다.
- * @param styler 스타일러
- * @return 현재 Formatter
- */
- public Formatter styler(Styler styler) {
- this.styler = styler;
- return this;
- }
-
- public Formatter onCell(Function, Runnable> func) {
- onCell = func;
- return this;
- }
- }
-
- /**셀 값과 스타일 설정에 대한 정의
- * @author mjkhan
- */
- public static class CellDef {
- /**valueMap에서 CellDef의 필드이름 또는 스타일을 설정한다.
- * @param defs CellDef 목록
- * @param valueMap 레이블별 필드이름 또는 스타일
- */
- public static void setValues(List defs, Map valueMap) {
- defs.forEach(def -> {
- Object val = valueMap.get(def.label);
- if (val == null)
- val = def.field;
- if (isEmpty(val))
- throw new RuntimeException("Value or style not found for " + def.label);
-
- def.value = val;
- });
- }
-
- /**CellDef 목록에서 셀헤더 이름과 스타일을 반환한다.
- * @param defs CellDef 목록
- * @param factory 헤더 스타일을 제공하는 function
- * @return 셀헤더 이름과 스타일 목록
- */
- public static List header(List defs, Supplier factory) {
- ArrayList result = new ArrayList<>();
-
- for (CellDef def: defs) {
- result.add(def.label);
-
- Styler styler = factory.get();
- styler.width(def.width);
- result.add(styler);
- }
-
- return result;
- }
-
- /**CellDef 목록에서 셀값의 필드이름 또는 스타일 목록을 반환한다.
- * @param defs CellDef 목록
- * @return 셀값의 필드이름 또는 스타일 목록
- */
- public static Object[] values(List defs) {
- return defs.stream().map(CellDef::getValue).toList().toArray();
- }
-
- public static TypeReference> listType() {
- return new TypeReference>() {};
- }
-
- private String
- label,
- field;
- private int width;
- private Object value;
-
- /**레이블을 반환한다.
- * @return 레이블
- */
- public String getLabel() {
- return label;
- }
-
- /**레이블을 설정한다.
- * @param label 레이블
- * @return 현재 CellDef
- */
- public CellDef setLabel(String label) {
- this.label = label;
- return this;
- }
-
- /**필드이름을 반환한다.
- * @return 필드이름
- */
- public String getField() {
- return field;
- }
-
- /**필드이름을 설정한다.
- * @param field 필드이름
- * @return 현재 CellDef
- */
- public CellDef setField(String field) {
- this.field = field;
- return this;
- }
-
- /**넓이를 반환한다.
- * @return 넓이
- * @return 현재 CellDef
- */
- public int getWidth() {
- return width;
- }
-
- /**넓이를 설정한다.
- * @param width 넓이
- * @return 현재 CellDef
- */
- public CellDef setWidth(int width) {
- this.width = width;
- return this;
- }
-
- /**필드이름, 또는 스타일을 반환한다.
- * @return 필드이름, 또는 스타일
- */
- public Object getValue() {
- return value;
- }
-
- /**필드이름, 또는 스타일을 설정한다.
- * @param value 필드이름, 또는 스타일
- * @return 현재 CellDef
- */
- public CellDef setValue(Object value) {
- this.value = value;
- return this;
- }
- }
-
- public static class CommentSupport {
- private XLSWriter writer;
- private XSSFWorkbook workbook;
- private CreationHelper factory;
- private ClientAnchor anchor;
- private Image image;
-
- public CommentSupport(XLSWriter writer) {
- this.writer = writer;
- workbook = this.writer.workbook.getXSSFWorkbook();
- factory = workbook.getCreationHelper();
- anchor = factory.createClientAnchor();
- image = new Image(this.writer);
- }
-
- public XSSFComment create(String str) {
- int row = writer.cell.getRowIndex();
- anchor.setRow1(row);
- anchor.setRow2(row + 17);
- int col = writer.cell.getColumnIndex();
- anchor.setCol1(col);
- anchor.setCol2(col + 6);
-
- SXSSFDrawing drawing = writer.worksheet.createDrawingPatriarch();
- XSSFComment comment = (XSSFComment)drawing.createCellComment(anchor);
- comment.setString(str);
- writer.cell.setCellComment(comment);
- return comment;
- }
-
- public void setBackgroundImage(String title, String path) {
- int picIndex = image.add(path);
- XSSFPictureData pic = workbook.getAllPictures().get(picIndex);
- XSSFVMLDrawing vml = writer.worksheet.getVMLDrawing(true);
- RelationPart rp = vml.addRelation(null, XSSFRelation.IMAGES, pic);
-
- int row = writer.cell.getRowIndex();
- int col = writer.cell.getColumnIndex();
- CTShape shape = vml.findCommentShape(row, col);
- CTFill fill = shape.getFillArray(0);
- fill.setColor2(fill.getColor());
- fill.unsetColor();
- fill.setRelid(rp.getRelationship().getId());
- fill.setTitle(title);
- fill.setRecolor(STTrueFalse.T);
- fill.setRotate(STTrueFalse.T);
- fill.setType(STFillType.FRAME);
- }
-
- public void setImageComment(String path) {
- create("");
- setBackgroundImage("", path);
- }
-
- public Runnable getImageCommenter(String path) {
- return () -> setImageComment(path);
- }
- }
-
- public static class Image {
- private XLSWriter writer;
-
- public Image(XLSWriter writer) {
- this.writer = writer;
- }
-
- public int add(InputStream input, int imgType) {
- try {
- return writer.workbook.addPicture(
- FileCopyUtils.copyToByteArray(input),
- imgType
- );
- } catch (Exception e) {
- throw runtimeException(e);
- }
- }
-
- public int add(String path) {
- String str = path.toLowerCase();
- int imgType = str.endsWith(".png") ? SXSSFWorkbook.PICTURE_TYPE_PNG : SXSSFWorkbook.PICTURE_TYPE_JPEG;
-
- try (FileInputStream input = new FileInputStream(path)) {
- return add(input, imgType);
- } catch (Exception e) {
- throw runtimeException(e);
- }
- }
- }
-}
\ No newline at end of file