前言
本文由作者三汪首發(fā)于簡(jiǎn)書漱办。
前幾天發(fā)了一篇文章你虹,提供了基于最新POI版本的Excel導(dǎo)出示例确憨,提供了網(wǎng)上各個(gè)現(xiàn)有代碼版本的deprecated警告的解決方案。今天來(lái)提供一個(gè)萬(wàn)能的導(dǎo)入導(dǎo)出工具類模板以及相應(yīng)示例。
工具類的思路和代碼骨架folk自素劍步輕塵啄栓,我個(gè)人基于實(shí)際需求對(duì)代碼進(jìn)行了重寫和優(yōu)化统屈,并補(bǔ)充完善了代碼注釋仑荐。查看工具類代碼已在開源中國(guó)上發(fā)布:獲取代碼戳這里码俩。
使用模板只需要將ExcelUtil.java和StringUtil.java復(fù)制到你的項(xiàng)目中即可。
【劃重點(diǎn):同步支持xls和xlsx版本扬霜。實(shí)現(xiàn)導(dǎo)入或者導(dǎo)出都只需要兩步操作定鸟。】
讀取Excel調(diào)用步驟:
1.定義需要讀取的表頭字段和表頭對(duì)應(yīng)的屬性字段
String keyValue ="手機(jī)名稱:phoneName,顏色:color,售價(jià):price";
2.讀取數(shù)據(jù)
List<PhoneModel> list = ExcelUtil.readExcel("test.xlsx",new FileInputStream("E://test.xlsx"),ExcelUtil.getMap(keyValue),"com.lkx.model.PhoneModel",1);
readExcel參數(shù)說(shuō)明:
/**
* readExcel:根據(jù)傳進(jìn)來(lái)的map集合讀取Excel以及model讀取Excel文件
*
* @author likaixuan,wolfgy
* @version 1.1 2017年9月18日
* @param fileName
* Excel文件名
* @param inputStream 輸入流
* @param map
* 表頭和屬性的Map集合,其中Map中Key為Excel列的名稱著瓶,Value為反射類的屬性
* @param classPath
* 需要映射的model的路徑
* @param rowNumIndex
* 表頭所在行數(shù)(從1開始联予,即第一行對(duì)應(yīng)行數(shù)1)
* @return List<T> 讀取到的數(shù)據(jù)集合
* @throws Exception
* @since JDK 1.7
*/
導(dǎo)出Excel調(diào)用步驟
1.定義需要讀取的表頭字段和表頭對(duì)應(yīng)的屬性字段
String keyValue ="手機(jī)名稱:phoneName,顏色:color,售價(jià):price";
2.導(dǎo)出
ExcelUtil.exportExcel("導(dǎo)出數(shù)據(jù)",new FileOutputStream("E://testOut.xls"), ExcelUtil.getMap(keyValue), list, "com.lkx.model.PhoneModel", null, null, null);
exportExcel參數(shù)說(shuō)明:
/**
*
* <p>
* Description:Excel導(dǎo)出<br />
* </p>
* @author likaixuan,wolfgy
* @version 1.1 2017年9月18日
* @param titleText 標(biāo)題欄內(nèi)容
* @param out 輸出流
* @param map 表頭和屬性的Map集合,其中Map中Key為Excel列的名稱,Value為反射類的屬性
* @param list 要輸出的對(duì)象集合
* @param classPath 需要映射的model的路徑
* @param titleStyle 標(biāo)題欄樣式蟹但。若為null則直接使用默認(rèn)樣式
* @param headStyle 表頭樣式躯泰。若為null則直接使用默認(rèn)樣式
* @param dataStyle 數(shù)據(jù)行樣式。若為null則直接使用默認(rèn)樣式
* @throws Exception
* @since JDK 1.7
* void
*/
下面簡(jiǎn)單粗暴上項(xiàng)目結(jié)構(gòu)和代碼华糖。
有什么意見麦向、見解或疑惑,歡迎留言討論客叉。
項(xiàng)目結(jié)構(gòu)
util層:ExcelUtil.java,StringUtil.java 實(shí)現(xiàn)導(dǎo)入導(dǎo)出Excel的工具類及其依賴的String工具類
web層:AssociationController.java 接口類
service層:StudentService.java 業(yè)務(wù)類
domain層:Student.java 學(xué)生實(shí)體
代碼展示
ExcelUtil.java
/**
* Project Name:excelutil
* File Name:ExcelUtil.java
* Package Name:com.lkx.util
* Date:2017年6月7日上午9:44:58
* Copyright (c) 2017~2020, likaixuan@test.com.cn All Rights Reserved.
*
*/
package com.wolfgy.util;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Serializable;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFFont;
import org.apache.poi.hssf.usermodel.HSSFRichTextString;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.HSSFColor.HSSFColorPredefined;
import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.ss.usermodel.FillPatternType;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.VerticalAlignment;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
public class ExcelUtil implements Serializable{
/**
* serialVersionUID
*/
private static final long serialVersionUID = 1L;
private static final Logger LOGGER = LoggerFactory
.getLogger(ExcelUtil.class);
//設(shè)置Excel讀取最大行數(shù)
private static final int MAX_ROW = 20000;
/**
* getMap:(將傳進(jìn)來(lái)的表頭和表頭對(duì)應(yīng)的屬性存進(jìn)Map集合诵竭,表頭字段為key,屬性為value)
*
* @author likaixuan,wolfgy
* @version 1.1 2017年9月18日
* @param 把傳進(jìn)指定格式的字符串解析到Map中
* 形如: String keyValue = "手機(jī)名稱:phoneName,顏色:color,售價(jià):price";
* @return Map<String, String> 轉(zhuǎn)換好的Map集合
* @since JDK 1.7
*/
public static Map<String, String> getMap(String keyValue) {
Map<String, String> map = new HashMap<>();
if (keyValue != null) {
String[] str = keyValue.split(",");
for (String element : str) {
String[] str2 = element.split(":");
map.put(str2[0], str2[1]);
}
}
return map;
}
/**
* readExcel:根據(jù)傳進(jìn)來(lái)的map集合讀取Excel以及model讀取Excel文件
*
* @author likaixuan,wolfgy
* @version 1.1 2017年9月18日
* @param fileName
* Excel文件名
* @param inputStream 輸入流
* @param map
* 表頭和屬性的Map集合,其中Map中Key為Excel列的名稱话告,Value為反射類的屬性
* @param classPath
* 需要映射的model的路徑
* @param rowNumIndex
* 表頭所在行數(shù)(從1開始,即第一行對(duì)應(yīng)行數(shù)1)
* @return List<T> 讀取到的數(shù)據(jù)集合
* @throws Exception
* @since JDK 1.7
*/
@SuppressWarnings({ "resource", "unchecked" })
public static <T> List<T> readExcel(String fileName, InputStream inputStream, Map<String,String> map,
String classPath, int rowNumIndex) throws Exception {
// 返回表頭字段名和屬性字段名Map集合中鍵的集合(Excel列的名稱集合)
Set<String> keySet = map.keySet();
//反射用
Class<?> demo = null;
Object obj = null;
List<Object> list = new ArrayList<Object>();
demo = Class.forName(classPath);
//獲取文件名后綴判斷文件類型
String fileType = fileName.substring(fileName.lastIndexOf(".") + 1,
fileName.length());
//根據(jù)文件類型及文件輸入流新建工作簿對(duì)象
Workbook wb = null;
if (fileType.equals("xls")) {
wb = new HSSFWorkbook(inputStream);
} else if (fileType.equals("xlsx")) {
wb = new XSSFWorkbook(inputStream);
} else {
LOGGER.error("您輸入的excel格式不正確");
throw new Exception("您輸入的excel格式不正確");
}
// 遍歷每個(gè)Sheet表
for (int sheetNum = 0; sheetNum < 1; sheetNum++) {
// 表頭成功讀取標(biāo)志位卵慰。當(dāng)表頭成功讀取后沙郭,rowNum_x值為表頭實(shí)際行數(shù)
int rowNum_x = -1;
// 存放每一個(gè)field字段對(duì)應(yīng)所在的列的序號(hào)
Map<String, Integer> cellmap = new HashMap<String, Integer>();
// 存放所有的表頭字段信息
List<String> headlist = new ArrayList<>();
// 獲取當(dāng)前Sheet表
Sheet hssfSheet = wb.getSheetAt(sheetNum);
//設(shè)置默認(rèn)最大行數(shù),當(dāng)超出最大行數(shù)時(shí)返回異常
if(hssfSheet != null && hssfSheet.getLastRowNum()>MAX_ROW){
throw new Exception("Excel 數(shù)據(jù)超過(guò)20000行,請(qǐng)檢查是否有空行,或分批導(dǎo)入");
}
// 遍歷Excel中的每一行
for (int rowNum = 0; rowNum <= hssfSheet.getLastRowNum(); rowNum++) {
// 當(dāng)表頭成功讀取標(biāo)志位rowNum_x為-1時(shí),說(shuō)明還未開始讀取數(shù)據(jù)裳朋。此時(shí)病线,如果傳值指定讀取其實(shí)行,就從指定行尋找鲤嫡,否則自動(dòng)尋找送挑。
if (rowNum_x == -1) {
//判斷指定行是否為空
Row hssfRow = hssfSheet.getRow(rowNumIndex);
if (hssfRow == null) {
throw new RuntimeException("指定的行為空,請(qǐng)檢查");
}
//設(shè)置當(dāng)前行為指定行
rowNum = rowNumIndex - 1;
}
//獲取當(dāng)前行
Row hssfRow = hssfSheet.getRow(rowNum);
//當(dāng)前行為空時(shí)暖眼,跳出本次循環(huán)進(jìn)入下一行
if (hssfRow == null) continue;
//當(dāng)前行數(shù)據(jù)為空時(shí)惕耕,跳出本次循環(huán)進(jìn)入下一行
boolean flag = false;
for (int i = 0; i < hssfRow.getLastCellNum(); i++) {
if (hssfRow.getCell(i) != null && !("").equals(hssfRow.getCell(i).toString().trim())) {
flag = true;
}
}
if (!flag) continue;
//獲取表頭內(nèi)容
if (rowNum_x == -1) {
// 循環(huán)列Cell
for (int cellNum = 0; cellNum <= hssfRow
.getLastCellNum(); cellNum++) {
Cell hssfCell = hssfRow.getCell(cellNum);
//當(dāng)前cell為空時(shí),跳出本次循環(huán)诫肠,進(jìn)入下一列司澎。
if (hssfCell == null) {
continue;
}
//獲取當(dāng)前cell的值(String類型)
String tempCellValue = hssfSheet.getRow(rowNum)
.getCell(cellNum).getStringCellValue();
//去除空格,空格ASCII碼為160
tempCellValue = StringUtils.remove(tempCellValue,
(char) 160);
tempCellValue = tempCellValue.trim();
//將表頭內(nèi)容放入集合
headlist.add(tempCellValue);
//遍歷表頭字段名和屬性字段名Map集合中鍵的集合(Excel列的名稱集合)
Iterator<String> it = keySet.iterator();
while (it.hasNext()) {
Object key = it.next();
if (StringUtils.isNotBlank(tempCellValue)
&& StringUtils.equals(tempCellValue,
key.toString())) {
//將rowNum_x設(shè)為實(shí)際的表頭行數(shù)
rowNum_x = rowNum;
//獲取表頭每一個(gè)field字段對(duì)應(yīng)所在的列的序號(hào)
cellmap.put(map.get(key).toString(), cellNum);
}
}
//當(dāng)rowNum_x為-1時(shí),說(shuō)明沒有在表頭找到對(duì)應(yīng)的字段或者對(duì)應(yīng)字段行上面含有不為空白的行字段栋豫,返回異常挤安。
if (rowNum_x == -1) {
LOGGER.error("沒有找到對(duì)應(yīng)的字段或者對(duì)應(yīng)字段行上面含有不為空白的行字段");
throw new Exception("沒有找到對(duì)應(yīng)的字段或者對(duì)應(yīng)字段行上面含有不為空白的行字段");
}
}
} else {
//實(shí)例化反射類對(duì)象
obj = demo.newInstance();
//遍歷并取出所需要的每個(gè)屬性值
Iterator<String> it = keySet.iterator();
while (it.hasNext()) {
//Excel列名
Object key = it.next();
//獲取屬性對(duì)應(yīng)列數(shù)
Integer cellNum_x = cellmap
.get(map.get(key).toString());
//當(dāng)屬性對(duì)應(yīng)列為空時(shí),結(jié)束本次循環(huán)笼才,進(jìn)入下次循環(huán)漱受,繼續(xù)獲取其他屬性值
if (cellNum_x == null || hssfRow.getCell(cellNum_x) == null) {
continue;
}
//得到屬性名
String attrName = map.get(key).toString();
//得到屬性類型
Class<?> attrType = BeanUtils.findPropertyType(attrName,
new Class[] { obj.getClass() });
//得到屬性值
Cell cell = hssfRow.getCell(cellNum_x);
Object val = getValue(cell, obj, attrName, attrType, rowNum, cellNum_x,
key);
setter(obj, attrName, val, attrType, rowNum, cellNum_x, key);
}
//將實(shí)例化好并設(shè)置完屬性的對(duì)象放入要返回的list中
list.add(obj);
}
}
}
wb.close();
inputStream.close();
return (List<T>) list;
}
/**
*
* <p>
* Description:setter(反射set方法給屬性賦值)<br />
* </p>
* @author likaixuan,wolfgy
* @version 1.1 2017年9月18日
* @param obj 反射類對(duì)象
* @param attrName 屬性名
* @param attrValue 屬性值
* @param attrType 屬性類型
* @param row 當(dāng)前數(shù)據(jù)在Excel中的具體行數(shù)
* @param column 當(dāng)前數(shù)據(jù)在Excel中的具體列數(shù)
* @param key 當(dāng)前數(shù)據(jù)對(duì)應(yīng)的Excel列名
* @since JDK 1.7
* @throws Exception
* void
*/
public static void setter(Object obj, String attrName, Object attrValue,
Class<?> attrType, int row, int column, Object key) throws Exception {
try {
//獲取反射的方法名
Method method = obj.getClass().getMethod(
"set" + StringUtil.toUpperCaseFirstOne(attrName), attrType);
//進(jìn)行反射
method.invoke(obj, attrValue);
} catch (Exception e) {
e.printStackTrace();
LOGGER.error("第" + (row + 1) + " 行 " + (column + 1) + "列 屬性:" + key
+ " 賦值異常 " + e.getStackTrace());
throw new Exception("第" + (row + 1) + " 行 " + (column + 1) + "列 屬性:"
+ key + " 賦值異常 ");
}
}
/**
* <p>
* Description:getter(反射get方法得到屬性值)<br />
* </p>
* @author likaixuan,wolfgy
* @version 1.1 2017年9月18日
* @param obj
* 反射類對(duì)象
* @param attrName
* 屬性名
* @throws Exception
* @since JDK 1.7
*/
public static Object getter(Object obj, String attrName)
throws Exception {
try {
//獲取反射的方法名
Method method = obj.getClass().getMethod("get" + StringUtil.toUpperCaseFirstOne(attrName));
Object value = new Object();
//進(jìn)行反射并獲取返回值
value = method.invoke(obj);
return value;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
*
* <p>
* Description:讀取當(dāng)前單元格的值<br />
* </p>
* @author likaixuan,wolfgy
* @version 1.1 2017年9月18日
* @param cell 單元格對(duì)象
* @param obj 反射類對(duì)象
* @param attrName 屬性名
* @param attrType 屬性類型
* @param row 當(dāng)前數(shù)據(jù)在Excel中的具體行數(shù)
* @param col 當(dāng)前數(shù)據(jù)在Excel中的具體列數(shù)
* @param key 當(dāng)前數(shù)據(jù)對(duì)應(yīng)的Excel列名
* @throws Exception
* @since JDK 1.7
* @return val 當(dāng)前單元格的值
*/
public static Object getValue(Cell cell, Object obj, String attrName,
Class<?> attrType, int row, int column, Object key) throws Exception {
//新建當(dāng)前單元格值對(duì)象
Object val = null;
//判斷當(dāng)前單元格數(shù)據(jù)類型并取值
if (cell.getCellTypeEnum() == CellType.BOOLEAN) {
val = cell.getBooleanCellValue();
} else if (cell.getCellTypeEnum() == CellType.NUMERIC) {
if (DateUtil.isCellDateFormatted(cell)) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
try {
if (attrType == String.class) {
val = sdf.format(DateUtil
.getJavaDate(cell.getNumericCellValue()));
} else {
val = StringUtil.dateConvertFormat(
sdf.format(DateUtil.getJavaDate(
cell.getNumericCellValue())));
}
} catch (ParseException e) {
LOGGER.error("日期格式轉(zhuǎn)換錯(cuò)誤");
throw new Exception("第" + (row + 1) + " 行 " + (column + 1)
+ "列 屬性:" + key + " 日期格式轉(zhuǎn)換錯(cuò)誤 ");
}
} else {
if (attrType == String.class) {
cell.setCellType(CellType.STRING);
val = cell.getStringCellValue();
} else if (attrType == BigDecimal.class) {
val = new BigDecimal(cell.getNumericCellValue());
} else if (attrType == long.class) {
val = (long) cell.getNumericCellValue();
} else if (attrType == Double.class) {
val = cell.getNumericCellValue();
} else if (attrType == Float.class) {
val = (float) cell.getNumericCellValue();
} else if (attrType == int.class || attrType == Integer.class) {
val = (int) cell.getNumericCellValue();
} else if (attrType == Short.class) {
val = (short) cell.getNumericCellValue();
} else {
val = cell.getNumericCellValue();
}
}
} else if (cell.getCellTypeEnum() == CellType.STRING) {
val = cell.getStringCellValue();
}
return val;
}
/**
*
* <p>
* Description:Excel導(dǎo)出<br />
* </p>
* @author likaixuan,wolfgy
* @version 1.1 2017年9月18日
* @param titleText 標(biāo)題欄內(nèi)容
* @param out 輸出流
* @param map 表頭和屬性的Map集合,其中Map中Key為Excel列的名稱络凿,Value為反射類的屬性
* @param list 要輸出的對(duì)象集合
* @param classPath 需要映射的model的路徑
* @param titleStyle 標(biāo)題欄樣式骡送。若為null則直接使用默認(rèn)樣式
* @param headStyle 表頭樣式。若為null則直接使用默認(rèn)樣式
* @param dataStyle 數(shù)據(jù)行樣式絮记。若為null則直接使用默認(rèn)樣式
* @throws Exception
* @since JDK 1.7
* void
*/
public static void exportExcel(String titleText,OutputStream out, Map<String,String> map,List<?> list, String classPath,HSSFCellStyle titleStyle,HSSFCellStyle headStyle,HSSFCellStyle dataStyle) throws Exception {
//創(chuàng)建單元格并設(shè)置單元格內(nèi)容
Set<String> keySet = map.keySet();// 返回鍵的集合
Iterator<String> it = keySet.iterator();
// 創(chuàng)建HSSFWorkbook對(duì)象(excel的文檔對(duì)象)
HSSFWorkbook workbook = new HSSFWorkbook();
// 建立新的sheet對(duì)象(excel的表單)
HSSFSheet sheet = workbook.createSheet("數(shù)據(jù)導(dǎo)出");
// 設(shè)置默認(rèn)列寬為15
sheet.setDefaultColumnWidth(15);
// 合并標(biāo)題欄單元格
sheet.addMergedRegion(new CellRangeAddress(0, 0, 0, keySet.size() - 1));
// 當(dāng)傳入的標(biāo)題欄樣式為空時(shí)摔踱,創(chuàng)建默認(rèn)標(biāo)題欄樣式
if (titleStyle == null) {
HSSFCellStyle style = workbook.createCellStyle();
style.setFillForegroundColor(HSSFColorPredefined.SKY_BLUE.getIndex());
style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
style.setBorderBottom(BorderStyle.THIN);
style.setBorderLeft(BorderStyle.THIN);
style.setBorderRight(BorderStyle.THIN);
style.setBorderTop(BorderStyle.THIN);
style.setAlignment(HorizontalAlignment.CENTER);
style.setVerticalAlignment(VerticalAlignment.CENTER);
HSSFFont font = workbook.createFont();
font.setColor(HSSFColorPredefined.VIOLET.getIndex());
font.setFontHeightInPoints((short) 18);
style.setFont(font);
titleStyle = style;
}
// 當(dāng)傳入的表頭樣式為空時(shí),創(chuàng)建默認(rèn)表頭樣式
if (headStyle == null) {
HSSFCellStyle style2 = workbook.createCellStyle();
style2.setFillForegroundColor(HSSFColorPredefined.GREEN.getIndex());
style2.setFillPattern(FillPatternType.SOLID_FOREGROUND);
style2.setBorderBottom(BorderStyle.THIN);
style2.setBorderLeft(BorderStyle.THIN);
style2.setBorderRight(BorderStyle.THIN);
style2.setBorderTop(BorderStyle.THIN);
style2.setAlignment(HorizontalAlignment.CENTER);
style2.setVerticalAlignment(VerticalAlignment.CENTER);
HSSFFont font2 = workbook.createFont();
font2.setFontHeightInPoints((short) 12);
style2.setFont(font2);
headStyle = style2;
}
// 當(dāng)傳入的數(shù)據(jù)行樣式為空時(shí)怨愤,創(chuàng)建默認(rèn)數(shù)據(jù)行樣式
if (dataStyle == null) {
HSSFCellStyle style3 = workbook.createCellStyle();
style3.setFillForegroundColor(HSSFColorPredefined.LIGHT_YELLOW.getIndex());
style3.setFillPattern(FillPatternType.SOLID_FOREGROUND);
style3.setBorderBottom(BorderStyle.THIN);
style3.setBorderLeft(BorderStyle.THIN);
style3.setBorderRight(BorderStyle.THIN);
style3.setBorderTop(BorderStyle.THIN);
style3.setAlignment(HorizontalAlignment.CENTER);
style3.setVerticalAlignment(VerticalAlignment.CENTER);
dataStyle = style3;
}
// 創(chuàng)建行派敷、單元格對(duì)象
HSSFRow row = null;
HSSFCell cell = null;
// 寫入標(biāo)題行
row = sheet.createRow(0);
row.setHeightInPoints(25);
cell = row.createCell(0);
cell.setCellStyle(titleStyle);
HSSFRichTextString textTitle = new HSSFRichTextString(titleText);
cell.setCellValue(textTitle);
//寫入表頭
row = sheet.createRow(1);//參數(shù)為行索引(excel的行),可以是0~65535之間的任何一個(gè)
Map<String,String> attrMap = new HashMap<>();
int index = 0;
while(it.hasNext()){
String key = it.next().toString();
cell = row.createCell(index);
cell.setCellValue(key);
cell.setCellStyle(headStyle);
attrMap.put(Integer.toString(index++), map.get(key).toString());
}
//寫入數(shù)據(jù)行
for(int i=2;i<list.size();i++){
row = sheet.createRow(i);
for(int j=0;j<map.size();j++){
//調(diào)用getter獲取要寫入單元格的數(shù)據(jù)值
Object value = getter(list.get(i), attrMap.get(Integer.toString(j)));
cell = row.createCell(j);
cell.setCellValue(value.toString());
cell.setCellStyle(dataStyle);
}
}
// 輸出Excel文件
try {
workbook.write(out);
out.flush();
out.close();
workbook.close();
LOGGER.info("導(dǎo)出成功!");
} catch (IOException e) {
LOGGER.info("IOException!導(dǎo)出失斪础篮愉!");
e.printStackTrace();
}
}
}
StringUtil.java
/**
* Project Name:excelutil
* File Name:StringUtil.java
* Package Name:com.lkx.util
* Date:2017年6月7日上午9:47:06
* Copyright (c) 2017~2020, likaixuan@test.com.cn All Rights Reserved.
*
*/
package com.wolfgy.util;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* ClassName:StringUtil
* Function: TODO ADD FUNCTION.
* Reason: TODO ADD REASON.
* Date: 2017年6月7日 上午9:47:06
* @author likaixuan
* @version V1.0
* @since JDK 1.7
* @see
*/
public class StringUtil {
/**
* 首字母轉(zhuǎn)小寫
*
* @param s
* @return
*/
public static String toLowerCaseFirstOne(String s) {
if (Character.isLowerCase(s.charAt(0))) {
return s;
} else {
return (new StringBuilder())
.append(Character.toLowerCase(s.charAt(0)))
.append(s.substring(1)).toString();
}
}
/**
* 首字母轉(zhuǎn)大寫
*
* @param s
* @return
*/
public static String toUpperCaseFirstOne(String s) {
if (Character.isUpperCase(s.charAt(0))) {
return s;
} else {
return (new StringBuilder())
.append(Character.toUpperCase(s.charAt(0)))
.append(s.substring(1)).toString();
}
}
/**
* replace:(替換字符串函數(shù))
*
* @param strSource
* 源字符串
* @param strFrom
* 要替換的子串
* @param strTo
* 替換為的字符串
* @return
* @since JDK 1.7
*/
public static String replace(String strSource, String strFrom,
String strTo) {
// 如果要替換的子串為空,則直接返回源串
if (strFrom == null || strFrom.equals(""))
return strSource;
String strDest = "";
// 要替換的子串長(zhǎng)度
int intFromLen = strFrom.length();
int intPos;
// 循環(huán)替換字符串
while ((intPos = strSource.indexOf(strFrom)) != -1) {
// 獲取匹配字符串的左邊子串
strDest = strDest + strSource.substring(0, intPos);
// 加上替換后的子串
strDest = strDest + strTo;
// 修改源串為匹配子串后的子串
strSource = strSource.substring(intPos + intFromLen);
}
// 加上沒有匹配的子串
strDest = strDest + strSource;
// 返回
return strDest;
}
/**
* String類型日期轉(zhuǎn)為Date類型
*
* @param dateStr
* @return
* @throws ParseException
* @throws Exception
*/
public static Date dateConvertFormat(String dateStr) throws ParseException {
Date date = new Date();
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
date = format.parse(dateStr);
return date;
}
}
Student.java
package com.wolfgy.domain;
import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import org.hibernate.annotations.GenericGenerator;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@Entity
@NoArgsConstructor
@Getter
@Setter
public class Student implements Serializable{
/**
* @fields serialVersionUID
*/
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(generator = "idGenerator")
@GenericGenerator(name = "idGenerator", strategy = "uuid")
private String id;
private String sName;
}
StudentService.java
//其余代碼略差导,只貼出導(dǎo)入導(dǎo)出相關(guān)方法
@Override
public void exportExcel(String[] ids, OutputStream out) {
String keyValue="學(xué)生ID:id,學(xué)生姓名:sName";
List<Student> list = new ArrayList<>();
for (int i = 0; i < ids.length; i++) {
Student student = repository.findOne(ids[i]);
list.add(student);
}
try {
ExcelUtil.exportExcel("學(xué)生數(shù)據(jù)導(dǎo)出", out, ExcelUtil.getMap(keyValue), list, "com.wolfgy.domain.Student", null, null, null);
logger.info("導(dǎo)出成功!");
} catch (Exception e) {
e.printStackTrace();
logger.info("導(dǎo)出失敗!");
}
}
@Override
public void importExcel(String fileName,InputStream in) {
logger.info("導(dǎo)入"+fileName+"開始");
String keyValue="學(xué)生ID:id,學(xué)生姓名:sName";
List<Student> list = null;
try {
//readExcel參數(shù)列表
//fileName Excel文件名
//inputStream 輸入流
//map 表頭和屬性的Map集合,其中Map中Key為Excel列的名稱试躏,Value為反射類的屬性
//classPath 需要映射的model的路徑
//rowNumIndex 表頭所在行數(shù)
list = ExcelUtil.readExcel("student.xlsx",in,ExcelUtil.getMap(keyValue),
"com.wolfgy.domain.Student",1);
logger.info(" 導(dǎo)入成功!");
} catch (Exception e) {
logger.error("導(dǎo)入失敗!");
}
for (Student student : list) {
logger.info("-------------");
logger.info("name:"+student.getSName());
}
logger.info(" 導(dǎo)入結(jié)束!");
}
AssociationController.java
//其余代碼略,只貼出導(dǎo)入導(dǎo)出相關(guān)方法
@RequestMapping(value = "/student/export" , method = RequestMethod.GET)
public void exporMemberFormExcel(@RequestParam(value = "ids", defaultValue = "", required = false) String[] ids, HttpServletResponse res) throws IOException {
logger.info("---------------導(dǎo)出列表到Excel--------------------");
res.setContentType("application/msexcel;charset=UTF-8");
res.addHeader("Content-Disposition", "attachment;filename=members.xls");
OutputStream out = res.getOutputStream();
studentService.exportExcel(ids, out);
}
@RequestMapping(value="/studen/ajaxUpload.do",method=RequestMethod.POST)
public void ajaxUploadExcel(@RequestParam("file") MultipartFile file) throws Exception{
if(!file.isEmpty()){
InputStream in = file.getInputStream();
String fileName = file.getName();
studentService.importExcel(fileName,in);
}else{
throw new BizException("上傳失敗设褐,因?yàn)槲募强盏?);
}
}
以上颠蕴。
希望我的文章對(duì)你能有所幫助泣刹。
我不能保證文中所有說(shuō)法的百分百正確,但我能保證它們都是我的理解和感悟以及拒絕復(fù)制黏貼犀被。
有什么意見椅您、見解或疑惑,歡迎留言討論寡键。