2017년 4월 28일

자바에서 엑셀 파일 만들기 : 아파치 POI 을 활용한 간단한 엑셀 생성 유틸리티 XSSFEExcelWriter

아파치 POI(Apache POI) 는 아파치 소프트웨어 재단에서 만든 라이브러리로 마이크로소프트 오프스 파일 포맷을 자바언어에서 읽고/쓰는 기능을 제공한다.

웹 프로그램을 개발 할 때 특정 데이터를 엑셀 파일로 다운로드하는 것은 아주 흔한일인데, 이러한 작업을 도와주는 유틸리티를 만들어 사용하는 것은 아주 많은 도움이 된다.

먼저 아파치 POI 사용을 위하여 아래와 같이 메이븐 pom.xml 파일에 라이브러리를 추가한다.

pom.xml
        
  
  
      org.apache.poi
      poi
      3.16
  

  
  
      org.apache.poi
      poi-ooxml
      3.16
  

 

유틸리티는 데이터베이스에서 조회된 결과 데이터를 손쉽게  엑셀파일로 생성하는 것에 목적을 두었다.
다음은 유틸리티 클래스 XSSFEExcelWriter.java 이다.

XSSFEExcelWriter.java
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
package architecture.community.util.excel;
 
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
 
import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.FillPatternType;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.usermodel.VerticalAlignment;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.apache.poi.xssf.usermodel.XSSFFont;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
 
 
/**
 * </p> 간단한 엑셀 생성 유틸리티 </p>
 * 
 * 
 * XSSFExcelWriter writer = new XSSFExcelWriter(); </br>
 *     // 작업할 시트를 추가한다.       </br></br>
 * 
 *     writer.createSheet("대상자 목록"); </br>
 *     // 첫번째 ROW 를 컬럼으로 사용하며 컬럼 인텍스 , 컬럼 이름, 값 데이터 추출을 위한 키, 마지막으로 필요시 컬럼의 폭을 지정한다.</br></br>
 *      
 *     writer.setColumn(0, "대상자여부", "EXCEL_CHECKFLAG", 3000);</br>
 *     writer.setColumn(1, "학과", "DVS_NAME", 5000);</br>
 *     writer.setColumn(2, "학번", "ID", 4000);</br>
 *     writer.setColumn(3, "성명", "NAME", 4000);</br>
 *     writer.setColumn(4, "학년", "CURRENT_CLASS", 3000);</br>
 *     writer.setHeaderToFirstRow(); </br></br>
 * 
 *  // 데이터 쓰기를 위한 데이터를 설정한다. 첫번째 ROW 다음부터 앞에서 지정한 컬럼 정보에 따라 쓰기를 진행한다. </br>
 *     writer.setData(items);</br></br>
 *      
 *     // 이함수를 호출해야 컬럼 폭을 설정에 따라 적용한다. (BUG)</br>
 *     writer.setColumnsWidth();</br></br>
 * 
 *     FileOutputStream fileOutStream = new FileOutputStream(new File("원하는 파일 경로"));</br>
 *     writer.write(fileOutStream);</br></br>
 *
 */
public class XSSFExcelWriter {
 
    private Logger log = LoggerFactory.getLogger(getClass());
    
    private XSSFWorkbook workbook;
 
    private int sheetIndex = 0;
    
    private List<Column> columns = new ArrayList<Column>();
    
    private XSSFCellStyle cellStyle;
    
    private static final String EMPTY_STRING = "";
    
    public XSSFExcelWriter() {
        this.workbook = new XSSFWorkbook();
    }
    
    public XSSFCellStyle getCellStyle() {
        if( cellStyle == null )
            cellStyle = this.createCellStyle();
        return cellStyle;
    }
 
    public void setCellStyle(XSSFCellStyle cellStyle) {
        this.cellStyle = cellStyle;
    }
 
    public XSSFWorkbook getWorkbook() {
        return workbook;
    }
 
    public int getSheetIndex() {
        return sheetIndex;
    }
 
    public void setSheetIndex(int sheetIndex) {
        this.sheetIndex = sheetIndex;
    }
 
    public void setWorkbook(XSSFWorkbook workbook) {
        this.workbook = workbook;
    }
 
    public void createSheet(String name) {
        XSSFSheet sheet = this.workbook.createSheet(name);
        this.sheetIndex = workbook.getSheetIndex(sheet);
    }
    
    public XSSFRow addRow(int rownum) {
        XSSFSheet sheet = getSheetAt(getSheetIndex());
        return sheet.createRow(rownum);
    }
    
    public XSSFCell addCell(int rownum, int column, XSSFCellStyle cellStyle) {
        XSSFCell cell = getRow(rownum).createCell(column);        
        if( cellStyle != null)
            cell.setCellStyle(cellStyle);
        
        return cell;
    }
 
    public XSSFSheet getSheetAt(int sheetIndex) {
        return workbook.getSheetAt(sheetIndex);
    }
    
    public int getFirstRowNum() {
        return getSheetAt(getSheetIndex()).getFirstRowNum();
       }
 
    public XSSFRow getRow(int rownum) {
        return getSheetAt(getSheetIndex()).getRow(rownum);
    }
    
    private XSSFCellStyle createCellStyle() {
        XSSFCellStyle style = workbook.createCellStyle();
        style.setVerticalAlignment(VerticalAlignment.CENTER);
        style.setBorderBottom(BorderStyle.THIN);
        style.setBottomBorderColor(IndexedColors.BLACK.index);        
        style.setBorderLeft(BorderStyle.THIN);
        style.setLeftBorderColor(IndexedColors.GREEN.index);
        style.setBorderRight(BorderStyle.THIN);
        style.setRightBorderColor(IndexedColors.BLUE.index);
        style.setBorderTop(BorderStyle.THIN);
        // style.setBorderTop(HSSFCellStyle.BORDER_MEDIUM_DASHED);
        style.setTopBorderColor(IndexedColors.BLACK.index);
        // style.setFillBackgroundColor(HSSFColor.GREY_25_PERCENT.index);        
        return style;
    }
    
    public void setHeaderToFirstRow () {        
        int rowNum = getFirstRowNum();
        XSSFRow row = addRow(rowNum);
        XSSFCellStyle cellStyle = createCellStyle();
        cellStyle.setFillForegroundColor(IndexedColors.GREY_80_PERCENT.index);
        cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
        cellStyle.setAlignment(HorizontalAlignment.CENTER_SELECTION);
        cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);        
        XSSFFont font = workbook.createFont();
        font.setBold(true);
        cellStyle.setFont(font);        
        for (Column c : columns) {
            XSSFCell cell = getRow(row.getRowNum()).createCell(c.columnIndex);            
            cell.setCellStyle(cellStyle);
            cell.setCellValue(c.name);
        }        
    }
 
    public int getLastRowNum() {
        return getSheetAt(getSheetIndex()).getLastRowNum();
    }
 
    public void setData(List<Map<String,Object>>  items ) {
        if( items != null ){
            for( Map<String,Object> item : items ){
                setDataToRow(item);
            }
        }
    }    
    
    public void setDataToRow(Map<String, Object> data ) {        
        XSSFRow row = addRow(getLastRowNum() + 1);
        for( Column c : columns )
        {
            XSSFCell cell = addCell(row.getRowNum(), c.columnIndex, getCellStyle());
            Object value = data.get(c.valueKey);    
            cell.setCellType(CellType.STRING);    
            if( value != null)
                cell.setCellValue( value.toString().trim());        
            else
                cell.setCellValue(EMPTY_STRING);
        }
    }
    
 
    public void write(File file) {
        FileOutputStream fs = null;
        try {
            // File.createTempFile(prefix, suffix);
            fs = new FileOutputStream(file);
            workbook.write(fs);
        } catch (IOException e) {
            log.error(e.getMessage(),e);
        } finally {
            if (fs != null)
                try {
                    fs.close();
                } catch (IOException e) {
                    log.error(e.getMessage(),e);
                }
        }
    }
 
    public void write(OutputStream output) {
        try {
            workbook.write(output);
        } catch (IOException e) {
            log.error(e.getMessage(), e);
        } finally {
            if (output != null)
                try {
                    output.close();
                } catch (IOException e) {
                    log.error(e.getMessage(), e);
                }
        }
    }
    
    public void setColumn(int idx, String name, String dataKey ){
        this.columns.add(new Column(idx, name, dataKey));
    }
    
    public void setColumn(int idx, String name, String dataKey, int width ){
        this.columns.add(new Column(idx, name, dataKey, width));
    }
    
    
    public void setColumnsWidth(){
        for (Column c : columns) {
            if(c.width > 0){
                getSheetAt(getSheetIndex()).setColumnWidth(c.columnIndex, c.width);
            }
        }
    }
    
    public static class Column {        
        String name;        
        String valueKey;        
        int columnIndex;        
        int width = 0 ;        
        public Column(int columnIndex, String name, String valueKey) {
            super();
            this.columnIndex = columnIndex;
            this.name = name;
            this.valueKey = valueKey;
        }
        
        public Column(int columnIndex, String name, String valueKey, int width ) {
            super();
            this.columnIndex = columnIndex;
            this.name = name;
            this.valueKey = valueKey;
            this.width = width;
        }
        
    } 
}
 
cs

다음은 이 유틸리티 클래스를 사용한 간단한 예이다.
또한 하나 이상의 시트를 만들고자하는 경우 역시 간단하게 createSheet 코드 부분부터 setColumnsWidth 코드 부분까지를 원하는데로 반복하여 사용하면 된다.

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
 
    @RequestMapping(value = "/export_excel.do", method = { RequestMethod.POST, RequestMethod.GET})
    @ResponseBody
    public void downloadExcel(HttpServletResponse response) throws IOException {     
        
        List<Map<String, Object>> list =  commonSrv.queryForList("SECURITY.SELECT_ALL_USER");
        
        XSSFExcelWriter writer = new XSSFExcelWriter();            
        writer.createSheet("사용자 목록");
        writer.setColumn(0"아이디""ID"4000);
        writer.setColumn(1"사번&학번""EMPNO"5000);
        writer.setColumn(2"성명""NAME"4000);
        writer.setColumn(3"메일""EMAIL"4000);
        writer.setColumn(4"전화""PHONE"4000);
        writer.setHeaderToFirstRow(); 
        writer.setData(list);
        writer.setColumnsWidth();
        response.setContentType("application/vnd.ms-excel");
        response.setHeader("Content-Disposition""attachment;filename=" + getEncodedFileName("사용자_익스포트.xlsx") );    
        writer.write(response.getOutputStream());
        response.flushBuffer();        
    }
    
    protected String getEncodedFileName(String filename) {
        try {
            return URLEncoder.encode(filename, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            return filename;
        }
    } 
cs


댓글 없음:

댓글 쓰기