μμ νμΌ μ λ‘λ λ€μ΄λ‘λ
μ΄λ νλ‘μ νΈλ₯Ό μ§ννλκ°μ μΉμΌλ‘ λ°μ΄ν°λ₯Ό κ΄λ¦¬νλλ° μμ νμΌ κΈ°λ₯μ΄ λΉ μ§ μ μλ€.
DBλ°μ΄ν°λ μ΄λ ν λ‘μ§μ μν κ²°κ³Όκ°μ μμ νμΌ ννλ‘ λ€μ΄λ‘λλ₯Ό λ°κ±°λ μμ λ‘ μ 리ν νμΌμ μ λ‘λν΄μ APIμ ν΄λΉ λ°μ΄ν°λ₯Ό λμ§κ±°λ DBμ μ μ₯νλ μμ μ κΌ νμνλ€.
μμ λ§ μνλ©΄ νλ‘κ·Έλ¨μ΄ νμμλ€λ λ§μ΄ μλ―μ΄, μΉμμμ μννκ² μμ νμΌμ νμ©ν μ μλλ‘ κ΄λ¦¬λꡬλ₯Ό λ§λ€μ΄μ£Όλ νλ‘κ·Έλ¨μ κΌ νμνλ€. μ΄μ μ μ¬λ¦° νμ΄μ¬μΌλ‘ μμ νμΌμ λ€λ‘λ λ²(https://myjamong.tistory.com/51) 보λ€λ μ‘°κΈ λ 볡μ‘ν κ΅¬μ‘°λ‘ λμ΄ μμ§λ§, μμ§μ μλ° μ€νλ§ νλ μμν¬λ₯Ό μ¬μ©νλ 곡곡 μ 체λ€μ΄ λ§μ κΌ μμλμΌνλ€κ³ μκ°νλ€.
μ€νλ§μ νμ©ν μμ νμΌ μ λ‘λ λ€μ΄λ‘λλ₯Ό ν λ§λ‘ μ‘κ³ λͺκ°μ κΈλ‘ λλ μ κΈ°λ³ΈλΆν° κ³ κΈλ΄μ©κΉμ§ μ€λͺ λ° μ€μ΅μ μ§νν μμ μ΄λ€.
POI λΌμ΄λΈλ¬λ¦¬
maven pom.xml
<!-- https://mvnrepository.com/artifact/org.apache.poi/poi-->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>4.0.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.9.0.pr4</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.7.9.1</version>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.2</version>
</dependency>
servlet-context
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<annotation-driven />
<resources mapping="/resources/**" location="/resources/" />
<beans:bean id="beanNameViewResolver" class="org.springframework.web.servlet.view.BeanNameViewResolver">
<beans:property name="order" value="0"/>
</beans:bean>
<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="prefix" value="/WEB-INF/views/" />
<beans:property name="suffix" value=".jsp" />
<beans:property name="order" value="1"></beans:property>
</beans:bean>
<beans:bean id="excelDownloadView" class="com.test.excel.util.ExcelDownloadView"/>
<beans:bean id="jsonView" class="org.springframework.web.servlet.view.json.MappingJackson2JsonView"/>
<beans:bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"/>
<context:component-scan base-package="com.*" />
</beans:beans>
μμ μ λ‘λ λ€μ΄λ‘λ νλ‘μ νΈ
Fruit.java
κ³ΌμΌκ°μ²΄κ° λ΄κΈ΄ 리μ€νΈλ₯Ό μμ±νμ¬ μμ νμΌλ‘ λ€μ΄λ‘λνλ μμ κ³Ό
λ€μ΄λ°μ μμ νμΌμ μ λ‘λνμ¬ κ³ΌμΌκ°μ²΄κ° λ΄κΈ΄ 리μ€νΈμ λ΄μ νλ©΄μ Jsonννλ‘ λΏλ €μ£Όλ μμ κΉμ§ μ§νν κ±°λ€.
package com.test.excel.vo;
public class Fruit {
String name;
long price;
int quantity;
public Fruit() {
}
public Fruit(String name, long price, int quantity) {
this.name = name;
this.price = price;
this.quantity = quantity;
}
public String getName() {
return name;
}
public long getPrice() {
return price;
}
public int getQuantity() {
return quantity;
}
public void setName(String name) {
this.name = name;
}
public void setPrice(long price) {
this.price = price;
}
public void setQuantity(int quantity) {
this.quantity = quantity;
}
}
ExcelDownloadView.java
package com.test.excel.util;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.springframework.web.servlet.view.AbstractView;
public class ExcelDownloadView extends AbstractView{
@Override
protected void renderMergedOutputModel(Map<String, Object> model, HttpServletRequest request, HttpServletResponse response)
throws Exception {
Locale locale = (Locale) model.get("locale");
String workbookName = (String) model.get("workbookName");
// κ²ΉμΉλ νμΌ μ΄λ¦ μ€λ³΅μ νΌνκΈ° μν΄ μκ°μ μ΄μ©ν΄μ νμΌ μ΄λ¦μ μΆ
Date date = new Date();
SimpleDateFormat dayformat = new SimpleDateFormat("yyyyMMdd", locale);
SimpleDateFormat hourformat = new SimpleDateFormat("hhmmss", locale);
String day = dayformat.format(date);
String hour = hourformat.format(date);
String fileName = workbookName + "_" + day + "_" + hour + ".xlsx";
// μ¬κΈ°μλΆν°λ κ° λΈλΌμ°μ μ λ°λ₯Έ νμΌμ΄λ¦ μΈμ½λ©μμ
String browser = request.getHeader("User-Agent");
if (browser.indexOf("MSIE") > -1) {
fileName = URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+", "%20");
} else if (browser.indexOf("Trident") > -1) { // IE11
fileName = URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+", "%20");
} else if (browser.indexOf("Firefox") > -1) {
fileName = "\"" + new String(fileName.getBytes("UTF-8"), "8859_1") + "\"";
} else if (browser.indexOf("Opera") > -1) {
fileName = "\"" + new String(fileName.getBytes("UTF-8"), "8859_1") + "\"";
} else if (browser.indexOf("Chrome") > -1) {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < fileName.length(); i++) {
char c = fileName.charAt(i);
if (c > '~') {
sb.append(URLEncoder.encode("" + c, "UTF-8"));
} else {
sb.append(c);
}
}
fileName = sb.toString();
} else if (browser.indexOf("Safari") > -1){
fileName = "\"" + new String(fileName.getBytes("UTF-8"), "8859_1")+ "\"";
} else {
fileName = "\"" + new String(fileName.getBytes("UTF-8"), "8859_1")+ "\"";
}
response.setContentType("application/download;charset=utf-8");
response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\";");
response.setHeader("Content-Transfer-Encoding", "binary");
OutputStream os = null;
SXSSFWorkbook workbook = null;
try {
workbook = (SXSSFWorkbook) model.get("workbook");
os = response.getOutputStream();
// νμΌμμ±
workbook.write(os);
}catch (Exception e) {
e.printStackTrace();
} finally {
if(workbook != null) {
try {
workbook.close();
} catch (Exception e) {
e.printStackTrace();
}
}
if(os != null) {
try {
os.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
μ€νλ§ μμ λ€μ΄λ‘λ μ λ‘λ
view
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<html>
<head>
<title>Home</title>
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
</head>
<body>
<script type="text/javascript">
function doExcelUploadProcess(){
var f = new FormData(document.getElementById('form1'));
$.ajax({
url: "uploadExcelFile",
data: f,
processData: false,
contentType: false,
type: "POST",
success: function(data){
console.log(data);
document.getElementById('result').innerHTML = JSON.stringify(data);
}
})
}
function doExcelDownloadProcess(){
var f = document.form1;
f.action = "downloadExcelFile";
f.submit();
}
</script>
<form id="form1" name="form1" method="post" enctype="multipart/form-data">
<input type="file" id="fileInput" name="fileInput">
<button type="button" onclick="doExcelUploadProcess()">μμ
μ
λ‘λ μμ
</button>
<button type="button" onclick="doExcelDownloadProcess()">μμ
λ€μ΄λ‘λ μμ
</button>
</form>
<div id="result">
</div>
</body>
</html>
μμ λ€μ΄λ‘λ
ExcelController 맀ν
@RequestMapping(value = "/downloadExcelFile", method = RequestMethod.POST)
public String downloadExcelFile(Model model) {
String[] names = {"μλͺ½", "μ νλ§κ³ ", "λ©λ‘ ", "μ€λ μ§"};
long[] prices = {5000, 10000, 7000, 6000};
int[] quantities = {50, 50, 40, 40};
List<Fruit> list = service.makeFruitList(names, prices, quantities);
SXSSFWorkbook workbook = service.excelFileDownloadProcess(list);
model.addAttribute("locale", Locale.KOREA);
model.addAttribute("workbook", workbook);
model.addAttribute("workbookName", "κ³ΌμΌν");
return "excelDownloadView";
}
ExcelService μμ μνΈ μμ± λ‘μ§
/**
* μμ
νμΌλ‘ λ§λ€ 리μ€νΈ μμ±
* @param names
* @param prices
* @param quantities
* @return μμ
νμΌ λ¦¬μ€νΈ
*/
public ArrayList<Fruit> makeFruitList(String[] names, long[] prices, int[] quantities){
ArrayList<Fruit> list = new ArrayList<Fruit>();
for(int i=0; i< names.length; i++) {
Fruit fruit = new Fruit(names[i], prices[i], quantities[i]);
list.add(fruit);
}
return list;
}
/**
* κ³ΌμΌ λ¦¬μ€νΈλ₯Ό κ°λ¨ν μμ
μν¬λΆ κ°μ²΄λ‘ μμ±
* @param list
* @return μμ±λ μν¬λΆ
*/
public SXSSFWorkbook makeSimpleFruitExcelWorkbook(List<Fruit> list) {
SXSSFWorkbook workbook = new SXSSFWorkbook();
// μνΈ μμ±
SXSSFSheet sheet = workbook.createSheet("κ³ΌμΌν");
//μνΈ μ΄ λλΉ μ€μ
sheet.setColumnWidth(0, 1500);
sheet.setColumnWidth(0, 3000);
sheet.setColumnWidth(0, 3000);
sheet.setColumnWidth(0, 1500);
// ν€λ ν μ
Row headerRow = sheet.createRow(0);
// ν΄λΉ νμ 첫λ²μ§Έ μ΄ μ
μμ±
Cell headerCell = headerRow.createCell(0);
headerCell.setCellValue("λ²νΈ");
// ν΄λΉ νμ λλ²μ§Έ μ΄ μ
μμ±
headerCell = headerRow.createCell(1);
headerCell.setCellValue("κ³ΌμΌμ΄λ¦");
// ν΄λΉ νμ μΈλ²μ§Έ μ΄ μ
μμ±
headerCell = headerRow.createCell(2);
headerCell.setCellValue("κ°κ²©");
// ν΄λΉ νμ λ€λ²μ§Έ μ΄ μ
μμ±
headerCell = headerRow.createCell(3);
headerCell.setCellValue("μλ");
// κ³ΌμΌν λ΄μ© ν λ° μ
μμ±
Row bodyRow = null;
Cell bodyCell = null;
for(int i=0; i<list.size(); i++) {
Fruit fruit = list.get(i);
// ν μμ±
bodyRow = sheet.createRow(i+1);
// λ°μ΄ν° λ²νΈ νμ
bodyCell = bodyRow.createCell(0);
bodyCell.setCellValue(i + 1);
// λ°μ΄ν° μ΄λ¦ νμ
bodyCell = bodyRow.createCell(1);
bodyCell.setCellValue(fruit.getName());
// λ°μ΄ν° κ°κ²© νμ
bodyCell = bodyRow.createCell(2);
bodyCell.setCellValue(fruit.getPrice());
// λ°μ΄ν° μλ νμ
bodyCell = bodyRow.createCell(3);
bodyCell.setCellValue(fruit.getQuantity());
}
return workbook;
}
/**
* μμ±ν μμ
μν¬λΆμ 컨νΈλ‘€λ μμ λ°κ²ν΄μ€ λ©μ
* @param list
* @return
*/
public SXSSFWorkbook excelFileDownloadProcess(List<Fruit> list) {
return this.makeSimpleFruitExcelWorkbook(list);
}
result
μμ μ λ‘λ
ExcelController 맀ν
@RequestMapping(value = "/uploadExcelFile", method = RequestMethod.POST)
public String uploadExcelFile(MultipartHttpServletRequest request, Model model) {
MultipartFile file = null;
Iterator<String> iterator = request.getFileNames();
if(iterator.hasNext()) {
file = request.getFile(iterator.next());
}
List<Fruit> list = service.uploadExcelFile(file);
model.addAttribute("list", list);
return "jsonView";
}
ExcelService μμ νμΌ μ λ‘λ ν κ³ΌμΌ λ¦¬μ€νΈλ‘ λ°ν λ‘μ§
/**
*μ
λ‘λν μμ
νμΌμ κ³ΌμΌ λ¦¬μ€νΈλ‘ λ§λ€κΈ°
* @param excelFile
* @return μμ±ν κ³ΌμΌ λ¦¬μ€νΈ
*/
public List<Fruit> uploadExcelFile(MultipartFile excelFile){
List<Fruit> list = new ArrayList<Fruit>();
try {
OPCPackage opcPackage = OPCPackage.open(excelFile.getInputStream());
XSSFWorkbook workbook = new XSSFWorkbook(opcPackage);
// 첫λ²μ§Έ μνΈ λΆλ¬μ€κΈ°
XSSFSheet sheet = workbook.getSheetAt(0);
for(int i=1; i<sheet.getLastRowNum() + 1; i++) {
Fruit fruit = new Fruit();
XSSFRow row = sheet.getRow(i);
// νμ΄ μ‘΄μ¬νκΈ° μμΌλ©΄ ν¨μ€
if(null == row) {
continue;
}
// νμ λλ²μ§Έ μ΄(μ΄λ¦λΆν° λ°μμ€κΈ°)
XSSFCell cell = row.getCell(1);
if(null != cell) fruit.setName(cell.getStringCellValue());
// νμ μΈλ²μ§Έ μ΄ λ°μμ€κΈ°
cell = row.getCell(2);
if(null != cell) fruit.setPrice((long)cell.getNumericCellValue());
// νμ λ€λ²μ§Έ μ΄ λ°μμ€κΈ°
cell = row.getCell(3);
if(null != cell) fruit.setQuantity((int)cell.getNumericCellValue());
list.add(fruit);
}
} catch (Exception e) {
e.printStackTrace();
}
return list;
}
result
POI λΌμ΄λΈλ¬λ¦¬ 1νΈμμλ κ°λ¨νκ² νμΌμ μ λ‘λνκ³ λ€μ΄λ‘λνλ κΈ°λ³Έμ μΈ μμ μ μ§ννλ€. μ΄λ €μ΄ μΈν λΆλΆμ λ€ μλ£λμλ€. μ΄μ λ ν΄λΉ λ‘μ§μ κ°κ° μ¬μ΄νΈμ λ§μΆ°μ μ¬μ©ν΄μ£Όλ©΄ λ°μ΄ν° μμ μ λλ¬λ€. μ΄μ λ€μ κΈλ€μμλ POI λΌμ΄λΈλ¬λ¦¬λ₯Ό μ¬μ©ν΄μ μμ νμΌμ λ€μ΄ λ°μλ μ€νμΌμ μ νκ±°λ μμμ μ¬μ©νλ λ‘μ§μ ꡬνν΄λ³Ό μμ μ΄λ€.
λκΈ