JXLS, XLSWriter 추가
parent
0f467b4158
commit
815ac2676e
@ -0,0 +1,15 @@
|
||||
package cokr.xit.base.file;
|
||||
|
||||
import java.io.OutputStream;
|
||||
|
||||
public interface Downloadable {
|
||||
String getFilename();
|
||||
|
||||
String getContentType();
|
||||
|
||||
String getDisposition();
|
||||
|
||||
Number getLength();
|
||||
|
||||
void write(OutputStream out);
|
||||
}
|
@ -1,229 +0,0 @@
|
||||
package cokr.xit.base.file;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.util.Date;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.apache.poi.ss.usermodel.Cell;
|
||||
import org.apache.poi.ss.usermodel.CellStyle;
|
||||
import org.apache.poi.ss.usermodel.Row;
|
||||
import org.apache.poi.xssf.usermodel.XSSFSheet;
|
||||
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
||||
import org.springframework.util.ResourceUtils;
|
||||
|
||||
import cokr.xit.foundation.AbstractComponent;
|
||||
import cokr.xit.foundation.data.StringMap;
|
||||
|
||||
/**엑셀 스프레드시트의 읽기나 쓰기를 돕는 유틸리티
|
||||
* @author mjkhan
|
||||
*/
|
||||
public class XLS extends AbstractComponent {
|
||||
/**엑셀 파일(*.xlsx)의 mime type */
|
||||
public static final String MIME_TYPE = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
|
||||
|
||||
/**워크시트에 데이터셋의 각 요소(row)의 값을 쓰기 위한 Functional interface
|
||||
* @author mjkhan
|
||||
* @param <E> 데이터셋의 요소(row) 유형
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public static interface Writer<E> {
|
||||
/**워크시트에 데이터셋의 각 요소(row)의 값을 쓴다.
|
||||
* @param sheet 워크시트
|
||||
* @param element 데이터셋의 각 요소(row)
|
||||
* @param index 데이터셋의 요소의 인덱스. 0부터 시작
|
||||
*/
|
||||
void write(XSSFSheet sheet, E element, int index);
|
||||
}
|
||||
|
||||
/**셀의 값을 읽어 반환한다.
|
||||
* @param cell 셀
|
||||
* @return 셀의 값
|
||||
*/
|
||||
public static Object getValue(Cell cell) {
|
||||
switch (cell.getCellType()) {
|
||||
case STRING: return cell.getStringCellValue();
|
||||
case NUMERIC: return cell.getNumericCellValue();
|
||||
case BOOLEAN: return cell.getBooleanCellValue();
|
||||
case BLANK: return "";
|
||||
default: return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**값을 셀에 설정한다.
|
||||
* @param cell Cell
|
||||
* @param value 값
|
||||
*/
|
||||
public static void setValue(Cell cell, Object value) {
|
||||
if (isEmpty(value)) {
|
||||
cell.setCellValue("");
|
||||
return;
|
||||
}
|
||||
|
||||
if (value instanceof String) {
|
||||
cell.setCellValue((String)value);
|
||||
} else if (value instanceof Number) {
|
||||
Number number = (Number)value;
|
||||
cell.setCellValue(number.doubleValue());
|
||||
} else if (value instanceof Date) {
|
||||
cell.setCellValue((Date)value);
|
||||
} else if (value instanceof Boolean) {
|
||||
Boolean b = (Boolean)value;
|
||||
cell.setCellValue(b.booleanValue());
|
||||
} else
|
||||
throw new IllegalArgumentException(value.getClass().getName() + ": " + value);
|
||||
}
|
||||
|
||||
private StringMap<CellStyle> styles;
|
||||
|
||||
public void setValue(String key, Cell cell, Object value) {
|
||||
setValue(cell, value);
|
||||
|
||||
if (styles == null)
|
||||
styles = new StringMap<>();
|
||||
|
||||
CellStyle style = styles.get(key);
|
||||
if (style == null)
|
||||
styles.put(key, style = cell.getCellStyle());
|
||||
|
||||
cell.setCellStyle(style);
|
||||
}
|
||||
|
||||
/**셀의 값을 읽어 String으로 반환한다.
|
||||
* @param cell 셀
|
||||
* @return 셀의 문자열값
|
||||
*/
|
||||
public static String getString(Cell cell) {
|
||||
Object value = getValue(cell);
|
||||
return isEmpty(value) ? ""
|
||||
: value instanceof String ? (String)value
|
||||
: value.toString();
|
||||
}
|
||||
|
||||
/**셀의 값을 읽어 Number로 반환한다.
|
||||
* @param cell 셀
|
||||
* @return
|
||||
* <ul><li>셀의 숫자값</li>
|
||||
* <li>값이 비어있으면 0</li>
|
||||
* </ul>
|
||||
*/
|
||||
public static Number getNumber(Cell cell) {
|
||||
Object value = getValue(cell);
|
||||
return isEmpty(value) ? 0
|
||||
: value instanceof Number ? (Number)value
|
||||
: value instanceof String ? Double.parseDouble((String)value)
|
||||
: 0;
|
||||
}
|
||||
|
||||
/**셀의 값을 읽어 Boolean으로 반환한다.
|
||||
* @param cell 셀
|
||||
* @return
|
||||
* <ul><li>셀의 Boolean값</li>
|
||||
* <li>값이 비어있으면 false</li>
|
||||
* </ul>
|
||||
*/
|
||||
public static Boolean getBoolean(Cell cell) {
|
||||
Object value = getValue(cell);
|
||||
return isEmpty(value) ? false
|
||||
: value instanceof Boolean ? (Boolean)value
|
||||
: Boolean.valueOf(value.toString());
|
||||
}
|
||||
|
||||
private XSSFWorkbook workbook;
|
||||
|
||||
/**FileInputStream에서 엑셀 스프레드시트를 읽어들인다.
|
||||
* @param input FileInputStream
|
||||
* @return XLS
|
||||
*/
|
||||
public XLS load(FileInputStream input) {
|
||||
try {
|
||||
workbook = new XSSFWorkbook(input);
|
||||
return this;
|
||||
} catch (Exception e) {
|
||||
throw applicationException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**지정한 경로의 파일에서 엑셀 스프레드시트를 읽어들인다.
|
||||
* @param path 파일 경로. classpath:..., 또는 file:...
|
||||
* @return XLS
|
||||
*/
|
||||
public XLS load(String path) {
|
||||
try (FileInputStream input = new FileInputStream(ResourceUtils.getFile(path))) {
|
||||
return load(input);
|
||||
} catch (Exception e) {
|
||||
throw applicationException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**엑셀 스프레드시트의 워크북을 반환한다.
|
||||
* @return 엑셀 스프레드시트의 워크북
|
||||
*/
|
||||
public XSSFWorkbook getWorkbook() {
|
||||
return ifEmpty(workbook, () -> workbook = new XSSFWorkbook());
|
||||
}
|
||||
|
||||
/**엑셀 스프레드시트에서 지정하는 인덱스의 워크시트를 반환한다.
|
||||
* @param index 워크시트 인덱스. 0부터 시작
|
||||
* @return 엑셀 스프레드시트 워크시트
|
||||
*/
|
||||
public XSSFSheet getWorksheet(int index) {
|
||||
int count = getWorkbook().getNumberOfSheets();
|
||||
return index < count ? workbook.getSheetAt(index) : workbook.createSheet();
|
||||
}
|
||||
|
||||
/**지정하는 인덱스의 워크시트를 읽는다.
|
||||
* @param sheetIndex 워크시트 인덱스. 0부터 시작
|
||||
* @param reader 워크시트의 각 row의 셀값을 읽어 작업을 수행하는 Function
|
||||
* @return XLS
|
||||
*/
|
||||
public XLS read(int sheetIndex, Consumer<Row> reader) {
|
||||
if (reader == null) return this;
|
||||
|
||||
XSSFSheet worksheet = getWorksheet(sheetIndex);
|
||||
for (Row row: worksheet) {
|
||||
reader.accept(row);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**지정하는 인덱스의 워크시트에 dataset의 각 row의 값들을 쓴다.
|
||||
* @param sheetIndex 워크시트 인덱스. 0부터 시작
|
||||
* @param dataset 데이터셋
|
||||
* @param writer dataset의 각 row의 값들을 워크시트에 쓰는 Function
|
||||
* @return XLS
|
||||
*/
|
||||
public <E, T extends Iterable<E>> XLS write(int sheetIndex, T dataset, Writer<E> writer) {
|
||||
XSSFSheet worksheet = getWorksheet(sheetIndex);
|
||||
if (!isEmpty(dataset)) {
|
||||
int index = -1;
|
||||
for (E e: dataset) {
|
||||
++index;
|
||||
writer.write(worksheet, e, index);
|
||||
}
|
||||
}
|
||||
if (styles != null) {
|
||||
styles.clear();
|
||||
styles = null;
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**지정하는 경로로 엑셀 스프레드시트를 저장하고 해당 파일을 반환한다.
|
||||
* @param path 저장할 파일 경로
|
||||
* @return 스프레드시트 파일
|
||||
*/
|
||||
public File write(String path) {
|
||||
if (workbook == null)
|
||||
throw new NullPointerException("No workbook to write");
|
||||
|
||||
try (FileOutputStream out = new FileOutputStream(path);) {
|
||||
workbook.write(out);
|
||||
return new File(path);
|
||||
} catch (Exception e) {
|
||||
throw applicationException(e);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,51 +1,43 @@
|
||||
package cokr.xit.base.file.web;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.net.URLEncoder;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.jxls.common.Context;
|
||||
import org.jxls.util.JxlsHelper;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.web.servlet.view.AbstractView;
|
||||
|
||||
import cokr.xit.foundation.Assert;
|
||||
|
||||
import cokr.xit.base.file.xls.XLS;
|
||||
|
||||
/**사용자가 요청하는 데이터를 엑셀파일로 제공하는 뷰.
|
||||
* 사용 순서는 다음과 같다.
|
||||
* 엑셀 템플릿파일 작성. 템플릿 작성법은
|
||||
* https://jxls.sourceforge.net
|
||||
* https://ddoriya.tistory.com/entry/JXLS-POI-JAVA%EC%97%90%EC%84%9C-Excel-%EC%82%AC%EC%9A%A9%ED%95%98%EB%8A%94-%EA%B5%AC%ED%98%84-%EB%B0%A9%EB%B2%95-%EB%B0%8F-%EC%A2%85%EB%A5%98-%EB%B9%84%EA%B5%90
|
||||
* 스프링 파일에 'xlsView' Bean 설정
|
||||
* 콘트롤러(*Controller.java)
|
||||
* ModelAndView의 이름을 'xlsView'로 지정
|
||||
* ModelAndView에
|
||||
* 엑셀 처리기 ('xls') 설정
|
||||
* DatasetControl (JSP / *.js)
|
||||
* 파라미터 설정
|
||||
* download() 호출
|
||||
*
|
||||
* @author mjkhan
|
||||
*/
|
||||
public class XLSView extends AbstractView {
|
||||
@Override
|
||||
protected void renderMergedOutputModel(Map<String, Object> model, HttpServletRequest hreq, HttpServletResponse hresp) throws Exception {
|
||||
try (InputStream input = getInputStream(model)) {
|
||||
String filename = getFilename(model);
|
||||
|
||||
Context ctx = new Context();
|
||||
model.forEach(ctx::putVar);
|
||||
XLS xls = (XLS)model.get("xls");
|
||||
|
||||
String charset = "UTF-8";
|
||||
String filename = xls.getFilename();
|
||||
|
||||
hresp.setCharacterEncoding(charset);
|
||||
hresp.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
||||
hresp.setContentType(XLS.MIME_TYPE);
|
||||
hresp.setHeader("Content-Disposition", "attachment; filename=\"" + URLEncoder.encode(filename, charset) +"\"");
|
||||
|
||||
JxlsHelper.getInstance().processTemplate(input, hresp.getOutputStream(), ctx);
|
||||
}
|
||||
}
|
||||
|
||||
private InputStream getInputStream(Map<String, Object> model) throws Exception {
|
||||
String path = (String)model.remove("template");
|
||||
if (Assert.isEmpty(path))
|
||||
throw new RuntimeException("'template' not found");
|
||||
|
||||
return new ClassPathResource(path).getInputStream();
|
||||
}
|
||||
|
||||
private String getFilename(Map<String, Object> model) {
|
||||
return Assert.ifEmpty(
|
||||
(String)model.remove("filename"),
|
||||
() -> new SimpleDateFormat("yyyyMMdd-HHmmss").format(new Date()) + ".xlsx"
|
||||
);
|
||||
xls.write(hresp.getOutputStream());
|
||||
}
|
||||
}
|
@ -0,0 +1,68 @@
|
||||
package cokr.xit.base.file.xls;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.jxls.common.Context;
|
||||
import org.jxls.util.JxlsHelper;
|
||||
|
||||
public class JXLS extends XLS {
|
||||
private Context ctx;
|
||||
private Map<String, Object> data;
|
||||
|
||||
@Override
|
||||
public JXLS setTemplate(String template) {
|
||||
super.setTemplate(template);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JXLS setFilename(String filename) {
|
||||
super.setFilename(filename);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**엑셀 파일에 저장할 데이터들을 반환한다.
|
||||
* @return 엑셀 파일에 저장할 데이터
|
||||
*/
|
||||
public Map<String, Object> getData() {
|
||||
return data != null ? data : Collections.emptyMap();
|
||||
}
|
||||
|
||||
/**엑셀 파일에 저장할 데이터들을 설정한다.
|
||||
* @param map 엑셀 파일에 저장할 데이터
|
||||
* @return 현재 XLS
|
||||
*/
|
||||
public JXLS setData(Map<String, Object> 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);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,67 @@
|
||||
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);
|
||||
}
|
@ -0,0 +1,728 @@
|
||||
package cokr.xit.base.file.xls;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.apache.poi.ss.usermodel.BorderStyle;
|
||||
import org.apache.poi.ss.usermodel.CellStyle;
|
||||
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.xssf.streaming.SXSSFCell;
|
||||
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.XSSFWorkbook;
|
||||
|
||||
/**대용량 데이터를 엑셀 파일로 저장하는 유틸리티.
|
||||
* XLSWriter는 엑셀 템플릿 파일을 사용하도록 할 수 있다.
|
||||
* <pre><code> XLSWriter xlsx = new XLSWriter().setTemplate("...");</code></pre>
|
||||
* XLSWriter가 데이터를 저장한 엑셀 파일을 다운로드할 때 사용할 이름을 지정할 수 있다.
|
||||
* <pre><code> XLSWriter xlsx = new XLSWriter()
|
||||
* .setTemplate("...")
|
||||
* .setFilename("...");</code></pre>
|
||||
* XLSWriter가 데이터를 엑셀로 저장하려면 워크시트와 작업셀을 지정해야 한다.
|
||||
* <pre><code> xlsx.worksheet(0) //워크시트 설정
|
||||
* .row(0) //첫번째 행
|
||||
* .col(0); //첫번째 열의 셀을 작업셀로 설정</code></pre>
|
||||
* 엑셀로 저장할 데이터를 준비한다.
|
||||
* <pre><code> List<DataObject> dataset = ...;</code></pre>
|
||||
* XLSWriter에 데이터를 설정한다.
|
||||
* <pre><code> xlsx.values(dataset);</code></pre>
|
||||
* 위 코드는 dataset의 모든 필드값들을 설정한다.
|
||||
* dataset의 특정 필드의 값들을 원하는 순서대로 설정하려면 해당 필드들의 이름을 순서대로 나열한다.
|
||||
* <pre><code> xlsx.values(dataset, "RCPT_ID", "RCPT_DT", "PAYER_NM", "RCPT_AMT");</code></pre>
|
||||
* dataset의 특정 필드의 값들에 스타일을 적용하려면 {@link KeyStyle}을 표시한다.
|
||||
* <pre><code> CellStyle
|
||||
* datetime = xlsx.yyyy_mm_dd_hh_mm_ss(),
|
||||
* numeric = xlsx.n_nn0();
|
||||
* xlsx.values(dataset, "RCPT_ID", xlsx.keyStyle("RCPT_DT", datetime), "PAYER_NM", xlsx.keyStyle("RCPT_AMT", numeric));</code></pre>
|
||||
* @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();
|
||||
}
|
||||
}
|
||||
|
||||
private SXSSFWorkbook getWorkbook() {
|
||||
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 = getWorkbook().getSheetAt(index);
|
||||
} catch (Exception e) {
|
||||
worksheet = getWorkbook().createSheet();
|
||||
}
|
||||
worksheet.setRandomAccessWindowSize(rowAccessWindowSize);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**지정한 이름의 워크시트를 반환한다.
|
||||
* 워크시트가 없으면 해당 이름의 워크시트를 생성 후 반환한다.
|
||||
* @param name 워크시트 이름
|
||||
* @return 워크시트
|
||||
*/
|
||||
public XLSWriter worksheet(String name) {
|
||||
try {
|
||||
SXSSFWorkbook wb = getWorkbook();
|
||||
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 val 설정값
|
||||
* @param style 적용할 스타일(CellStyle, Styler, 또는 KeyStyle)
|
||||
* @return 현재 XLSWriter
|
||||
*/
|
||||
public XLSWriter value(Object val, Object style) {
|
||||
if (isEmpty(val))
|
||||
return this;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/**지정한 값들을 현재 작업셀부터 행으로 순서대로 설정한다.<br />
|
||||
* 값이 설정된 셀에 스타일을 적용하려면 해당값의 바로 뒤에 스타일을 지정한다.<br />
|
||||
* 다음은 사용례다.
|
||||
* <pre><code> XLSWriter xlsx = new XLSWriter()
|
||||
* .setTemplate("...") // 템플릿 사용 시 지정
|
||||
* .setFilename("...") // 다운로드 시 파일이름 지정
|
||||
* .worksheet(0) // 워크시트 지정
|
||||
* .cell(0, 0) // 작업셀 지정
|
||||
* .rowValues(List.of("하나", 10000, new Date()));</code></pre>
|
||||
* 두번째 값에는 숫자포맷을, 세번째 값에는 날짜포맷을 지정하려면 다음과 같이 한다.
|
||||
* <pre><code> 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));</code></pre>
|
||||
* @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 KeyStyle) {
|
||||
setCellStyle(val);
|
||||
} 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 KeyStyle) {
|
||||
KeyStyle keyStyle = (KeyStyle)obj;
|
||||
styler = keyStyle.styler;
|
||||
style = keyStyle.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<Object> vals = new ArrayList<>();
|
||||
for (Object obj: keysAndStyles) {
|
||||
if (obj instanceof KeyStyle) {
|
||||
KeyStyle keyStyle = (KeyStyle)obj;
|
||||
Object val = map.get(keyStyle.key);
|
||||
vals.add(val);
|
||||
vals.add(keyStyle);
|
||||
} else {
|
||||
vals.add(map.get(obj));
|
||||
}
|
||||
}
|
||||
return vals;
|
||||
}
|
||||
|
||||
/**지정한 map의 값들을 현재 작업셀부터 행으로 설정한다.<br />
|
||||
* 설정할 값과 순서를 정하려면 해당 값들의 키를 지정한다.<br />
|
||||
* 값이 설정된 셀에 스타일을 적용하려면 {@link KeyStyle}로 키와 스타일을 지정한다.<br />
|
||||
* 다음은 map의 모든 값들을 설정하는 예다.
|
||||
* <pre><code> 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);</code></pre>
|
||||
* 설정할 값들을 지정하려면 다음과 같이 한다.
|
||||
* <pre><code> xlsx.rowValues(rec, "PAYER", "RCPT_AMT", "RCPT_DT");</code></pre>
|
||||
* RCPT_AMT, RCPT_DT에 숫자포맷과 날짜포맷을 적용하려면 다음과 같이 한다.
|
||||
* <pre><code> 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));</code></pre>
|
||||
* @param map 맵
|
||||
* @param keysAndStyles 셀에 설정할 값들의 키, 또는 {@link KeyStyle 키와 스타일}
|
||||
* @return 현재 XLSWriter
|
||||
*/
|
||||
public XLSWriter rowValues(Map<?, ?> map, Object... keysAndStyles) {
|
||||
return rowValues(vals(map, keysAndStyles));
|
||||
}
|
||||
|
||||
/**지정한 데이터셋의 값들을 현재 작업셀부터 행과 열로 설정한다.
|
||||
* 설정할 값과 순서를 정하려면 해당 값들의 키를 지정한다.<br />
|
||||
* 값이 설정된 셀에 스타일을 적용하려면 {@link KeyStyle}로 키와 스타일을 지정한다.<br />
|
||||
* 다음은 데이터셋의 모든 값들을 설정하는 예다.
|
||||
* <pre><code> List<DataObject> dataset = ...;
|
||||
* XLSWriter xlsx = new XLSWriter()
|
||||
* .setTemplate("...") // 템플릿 사용 시 지정
|
||||
* .setFilename("...") // 다운로드 시 파일이름 지정
|
||||
* .worksheet(0) // 워크시트 지정
|
||||
* .cell(0, 0) // 작업셀 지정
|
||||
* .rowValues(dataset);</code></pre>
|
||||
* 설정할 값들을 지정하려면 다음과 같이 한다.
|
||||
* <pre><code> xlsx.rowValues(dataset, "PAYER", "RCPT_AMT", "RCPT_DT");</code></pre>
|
||||
* RCPT_AMT, RCPT_DT에 숫자포맷과 날짜포맷을 적용하려면 다음과 같이 한다.
|
||||
* <pre><code> CellStyle numeric = xlsx.n_nn0(); //{@link #cellStyle(Styler)} 참고
|
||||
* CellStyle datetime = xlsx.yyyy_mm_dd_hh_mm_ss();
|
||||
* ...
|
||||
* xlsx.rowValues(dataset, "PAYER", xlsx.keyStyle("RCPT_AMT", numeric), xlsx.keyStyle("RCPT_DT", datetime));</code></pre>
|
||||
* @param dataset 데이터셋
|
||||
* @param keysAndStyles 셀에 설정할 값들의 키, 또는 {@link KeyStyle 키와 스타일}
|
||||
* @return 현재 XLSWriter
|
||||
*/
|
||||
public XLSWriter values(Iterable<? extends Map<?, ?>> dataset, Object... keysAndStyles) {
|
||||
if (!isEmpty(dataset)) {
|
||||
int c = cell.getColumnIndex(),
|
||||
r = cell.getRowIndex();
|
||||
for (Map<?, ?> rec: dataset) {
|
||||
cell(r, c);
|
||||
rowValues(rec, keysAndStyles);
|
||||
++r;
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public XLSWriter styles(Styler... stylers) {
|
||||
if (!isEmpty(stylers)) {
|
||||
int start = cell.getColumnIndex(),
|
||||
x = start;
|
||||
for (Styler styler: stylers) {
|
||||
col(x);
|
||||
setCellStyle(styler);
|
||||
++x;
|
||||
}
|
||||
col(start);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**스타일 정보에서 셀스타일을 생성하여 반환한다.
|
||||
* @param styler 스타일 정보
|
||||
* @return 셀스타일
|
||||
*/
|
||||
public CellStyle cellStyle(Styler styler) {
|
||||
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 KeyStyle keyStyle(Object key, CellStyle style) {
|
||||
return new KeyStyle(key, style);
|
||||
}
|
||||
|
||||
/**style에서 셀스타일을 생성한 후 지정한 키와 연결한 KeyStyle을 반환한다.
|
||||
* @param key 키
|
||||
* @param style 스타일 정보
|
||||
* @return
|
||||
*/
|
||||
public KeyStyle keyStyle(Object key, Styler style) {
|
||||
return keyStyle(key, cellStyle(style));
|
||||
}
|
||||
|
||||
/**현재 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("#,###"));
|
||||
}
|
||||
|
||||
/**숫자 스타일(오른쪽 정렬, 천단위 구분, 소수점 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));
|
||||
}
|
||||
|
||||
/**셀스타일 정보. {@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<Styler> 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 KeyStyle {
|
||||
private Object key;
|
||||
private CellStyle style;
|
||||
private Styler styler;
|
||||
|
||||
/**새 KeyStyle을 생성한다.
|
||||
* @param key 키
|
||||
* @param style 셀스타일
|
||||
*/
|
||||
KeyStyle(Object key, CellStyle style) {
|
||||
this.key = notEmpty(key, "key");
|
||||
this.style = style;
|
||||
}
|
||||
|
||||
/**새 KeyStyle을 생성한다.
|
||||
* @param key 키
|
||||
* @param styler 스타일러
|
||||
*/
|
||||
KeyStyle(Object key, Styler styler) {
|
||||
this.key = notEmpty(key, "key");
|
||||
this.styler = styler;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue