您的位置:首页 > 编程语言 > Java开发

灵活的 反射 多sheet 导入导出 Excel 工具类

2018-03-21 11:55 543 查看
<!--excel导入导出start-->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.8</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.8</version>
</dependency>
<!--excel导入导出end-->
在pom.xml中引入导入导出Jar包。
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
* excel导入导出注解类
* Created by zxy on 2017/11/1.
*/
@Target({ ElementType.METHOD, ElementType.FIELD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
public @interface ExcelField {
//导入导出字段在excel中的名字
String title();
}
ExcelField注释类
import org.springframework.util.StringUtils;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.Date;

public class MyUtils {

//获取格式化的时间,参数都为空则返回当前时间
public static final String getFormatDate(String style, Date date) {
return new SimpleDateFormat(isEmpty(style) ? "yyyy-MM-dd" : style).format(date == null ? new Date() : date);
}

//判断为null或空字符串
public static final boolean isEmpty(String s) {
return StringUtils.isEmpty(s);
}

//URL 编码, Encode默认为UTF-8.
public static final String urlEncode(String s) throws UnsupportedEncodingException {
return URLEncoder.encode(s, "UTF-8");
}
}
MyUtils工具类import com.zxy.whbackstage.common.MyUtils;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFFont;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.usermodel.*;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
*
* @Description: excel导出封装类
* @author zxy
* @date 2017年11月1日
*/
public class ExcelUtil
{
//通用
public static <Q> void writeExcel(HttpServletResponse response, String fileName, List<Q> list, Class<Q> cls) throws IOException, IllegalArgumentException, IllegalAccessException
{
HSSFWorkbook wb = new HSSFWorkbook();

Field[] fields = cls.getDeclaredFields();
ArrayList<String> headList = new ArrayList<String>();

for (Field f : fields)
{
ExcelField field = f.getAnnotation(ExcelField.class);
if (field != null)
{
headList.add(field.title());
}
}

CellStyle style = getCellStyle(wb);
List<List<Q>> listTemp = new ArrayList<>();
if(list!=null){
int total = list.size();
int cycelTotal = total / 65000;
int tt = 0;
for (int i = 0; i <= cycelTotal; i++) {
if(((i+1)*65000)>total){
tt = total;
}else{
tt = ((i+1)*65000);
}
listTemp.add(list.subList(i*65000,tt));
}
}
for (int k = 0; k < listTemp.size(); k++) {
Sheet sheet = wb.createSheet();
/**
* 设置Excel表的第一行即表头
*/
Row row = sheet.createRow(0);
for (int i = 0; i < headList.size(); i++)
{
Cell headCell = row.createCell(i);
headCell.setCellType(Cell.CELL_TYPE_STRING);
headCell.setCellStyle(style);//设置表头样式
headCell.setCellValue(String.valueOf(headList.get(i)));
sheet.autoSizeColumn((short) i);// 设置单元格自适应
//sheet.setColumnWidth(0, 15 * 256);
}
if(listTemp.get(k)!=null){
for (int i = 0; i < listTemp.get(k).size(); i++)
{
Row rowdata = sheet.createRow(i + 1);//创建数据行
Q q = listTemp.get(k).get(i);
Field[] ff = q.getClass().getDeclaredFields();
int j = 0;
for (Field f : ff)
{
ExcelField field = f.getAnnotation(ExcelField.class);
if (field == null)
{
continue;
}
f.setAccessible(true);
Object obj = f.get(q);
Cell cell = rowdata.createCell(j);
cell.setCellType(Cell.CELL_TYPE_STRING);
// 当数字时
if (obj instanceof Integer) cell.setCellValue((Integer) obj);
// 当长整形
if (obj instanceof Long) cell.setCellValue((Long) obj);
// 当为字符串时
if (obj instanceof String) cell.setCellValue((String) obj);
// 当为布尔时
if (obj instanceof Boolean) cell.setCellValue((Boolean) obj);
// 当为时间时
if (obj instanceof Date) cell.setCellValue(MyUtils.getFormatDate("yyyy-MM-dd", (Date) obj));
// 当为时间时
if (obj instanceof Calendar) cell.setCellValue((Calendar) obj);
// 当为小数时
if (obj instanceof Double) cell.setCellValue((Double) obj);
//将序号替换为123456
if (j == 0) cell.setCellValue(i + 1);
j++;
}
}
}

}
response.setContentType( "application/octet-stream");
response.setHeader("Content-Disposition", "attachment;filename=report.zip");
OutputStream ouputStream = null;
try
{
ouputStream = response.getOutputStream();
ZipOutputStream zip = new ZipOutputStream(ouputStream);
ZipEntry entry = new ZipEntry(MyUtils.urlEncode(fileName));
zip.putNextEntry(entry);
wb.write(zip);
zip.flush();
zip.close();
}
finally
{
ouputStream.flush();
ouputStream.close();
}
}

/**
*
* @Description:设置表头样式
* @author zxy
* @date 2017年11月1日
*/
public static CellStyle getCellStyle(Workbook wb)
{
CellStyle style = wb.createCellStyle();
Font font = wb.createFont();
font.setFontName("宋体");
font.setFontHeightInPoints((short) 12);//设置字体大小
font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);//加粗
style.setFillForegroundColor(HSSFColor.LIME.index);// 设置背景色
style.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
style.setAlignment(HSSFCellStyle.SOLID_FOREGROUND);//让单元格居中
style.setAlignment(HSSFCellStyle.ALIGN_CENTER);// 左右居中
style.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);// 上下居中
style.setWrapText(true);//设置自动换行
style.setFont(font);
return style;
}

}excel导出封装类
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.ss.usermodel.*;

import java.io.*;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

/**
*
* @Description: excel导入封装类
* @author zxy
* @date 2017年11月28日
*/
@Slf4j
public class ReadExcelUtil {

public static <Q> List<Q> getExcelAsFile(String file,Class<Q> cls) throws FileNotFoundException, IOException, InvalidFormatException {
List<Q> list = new ArrayList<Q>();
Field[] fields = cls.getDeclaredFields();
ArrayList<String> headList = new ArrayList<String>();
InputStream ins = null;
Workbook wb = null;
ins=new FileInputStream(new File(file));
//得到Excel工作簿对象
wb = WorkbookFactory.create(ins);
ins.close();
int sheetNum = wb.getNumberOfSheets();
boolean falg = false;
for (int i = 0; i < sheetNum; i++) {
//得到Excel工作表对象
Sheet sheet = wb.getSheetAt(i);
//总行数
int trLength = sheet.getLastRowNum();
//数据行读取
for (int j = 1; j < trLength+1; j++) {
try {
Q shixin = cls.newInstance();
Row row = sheet.getRow(j);
falg = false;
for (Field f : fields) {
ExcelField field = f.getAnnotation(ExcelField.class);
if (field != null){
//标题行
Row rowt = sheet.getRow(0);
for (int k = 0; k < rowt.getLastCellNum(); k++) {
Cell cellt = rowt.getCell(k);
if(cellt==null){
continue;
}
int cellTypet = cellt.getCellType();
if(cellTypet==1&&cellt.getStringCellValue().equals(field.title())){
falg = true;
if(row==null){
continue;
}
Cell cell = row.getCell(k);
if(cell==null){
falg = false;
break;
}
int cellType = cell.getCellType();
String typeName = f.getGenericType().getTypeName();
//得到单元格类型
switch (cellType){
case 0:
//CELL_TYPE_NUMERIC
f.setAccessible(true);
if("java.lang.String".equals(typeName)){
if(cellType == HSSFCell.CELL_TYPE_NUMERIC){
cell.setCellType(HSSFCell.CELL_TYPE_STRING);
f.set(shixin,cell.toString());
}
}else if("java.lang.Long".equals(typeName)){
if(cellType == HSSFCell.CELL_TYPE_NUMERIC){
cell.setCellType(HSSFCell.CELL_TYPE_STRING);
f.set(shixin,Long.parseLong(cell.toString()));
}
}else if("java.lang.Integer".equals(typeName)){
f.set(shixin,new Double(cell.getNumericCellValue()).intValue());
}else if("java.lang.Double".equals(typeName)){
f.set(shixin,cell.getNumericCellValue());
}
break;
case 1:
//CELL_TYPE_STRING
f.setAccessible(true);
if("java.lang.String".equals(typeName)){
f.set(shixin,cell.getStringCellValue());
}else if("java.lang.Long".equals(typeName)){
if(!"".equals(cell.getStringCellValue().trim())){
f.set(shixin,Long.parseLong(cell.getStringCellValue()));
}else{
falg = false;
}
}else if("java.lang.Integer".equals(typeName)){
if(!"".equals(cell.getStringCellValue().trim())){
f.set(shixin,Integer.parseInt(cell.getStringCellValue()));
}else{
falg = false;
}
}else if("java.lang.Double".equals(typeName)){
if(!"".equals(cell.getStringCellValue().trim())){
f.set(shixin,Double.parseDouble(cell.getStringCellValue()));
}else{
falg = false;
}
}
break;
case 2:
//CELL_TYPE_FORMULA
//cell.getCellFormula();
//System.out.println(cell.getCellFormula());
break;
case 3:
//CELL_TYPE_BLANK
break;
case 4:
//CELL_TYPE_BOOLEAN
f.setAccessible(true);
if("java.lang.Boolean".equals(typeName)){
f.set(shixin,cell.getBooleanCellValue());
}
//cell.getBooleanCellValue();
//System.out.println(cell.getBooleanCellValue());
break;
case 5:
//CELL_TYPE_ERROR
//cell.getErrorCellValue();
//System.out.println(cell.getErrorCellValue());
break;
default:
break;
}
}
}
}
}
if(falg){
list.add(shixin);
}
} catch (InstantiationException e) {
log.info("第"+j+"行出错");
log.info(e.getMessage());
} catch (IllegalAccessException e) {
log.info("第"+j+"行出错");
log.info(e.getMessage());
}
}
}
return list;
}
}execl导入封装类
完成,以上工具类已经可以导入导出了。下面来介绍下用法。
import com.zxy.whbackstage.common.excelUtils.ExcelField;
import lombok.Data;

@Data
public class ExportAdmin {
@ExcelField(title = "序号")
private Integer No;

@ExcelField(title = "登录账号")
private String userName;

@ExcelField(title = "真实姓名")
private String trueName;

@ExcelField(title = "密码")
private String password;

private String gender;

private String mobile;
}注意看ExportAdmin这个类,你要导出哪个字段的数据就在哪个数据上标识@ExcelField(title="序号"),其中title就是对应的导出的excel的列名。
@RequestMapping(value = "/export", method = RequestMethod.GET)
public void exportOrderList(HttpServletResponse response){
List<ExportAdmin> list = new ArrayList<>();
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
String fileName = sdf.format(new Date())+"excel.xls";
try {
ExcelUtil.writeExcel(response, fileName, list, ExportAdmin.class);
} catch (IOException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}以上就是Controller调用了。list就是从后台数据库读取的ExportAdmin的集合。至此后台导出功能就完成了。下面介绍导入功能。
import com.zxy.whbackstage.common.excelUtils.ExcelField;
import lombok.Data;

@Data
public class InputAdmin {
@ExcelField(title = "序号")
private Integer No;

@ExcelField(title = "登录账号")
private String userName;

@ExcelField(title = "真实姓名")
private String trueName;

@ExcelField(title = "密码")
private String password;

private String gender;

private String mobile;
}注意InputAdmin这个类和ExportAdmin这个类一样的呢?确实一样的,这些实体类按照你的业务需求可以合并成一个实体类。
导入和导出的正好相反,注意@ExcelField中的title,导入的excel列标题头必须和title中的中文或者英文字符相匹配。例如:



这个excel是要导入的数据,只有序号,登录账号,真实姓名,密码这4个@ExcelField标识的列的数据能读取出来,性别和手机会被忽略。
@ResponseBody
@RequestMapping(value = "/saveGoodsOrderFile", method = RequestMethod.POST,consumes = "multipart/form-data")
public String saveGoodsOrderFile(@RequestParam("fileName") MultipartFile file,
HttpServletRequest request) {
// 判断文件是否为空
if (!file.isEmpty()) {
try {
String filePath = request.getSession().getServletContext().getRealPath("/")+"file/temp/"
+ file.getOriginalFilename();
File file2=new File(filePath);
file.transferTo(file2);
List<InputAdmin> list = ReadExcelUtil.getExcelAsFile(filePath,InputAdmin.class);
//this.orderChildService.saveTicketFile(list);
if(file2.exists()){
file2.delete();
}
} catch (Exception e) {
e.printStackTrace();
}
}
return "";
}这个就是Controller调用方法,把excel文件中一行数据包装成一个InputAdmin实体类,通过工具类得到InputAdmin的List集合。至此就把excel文件里面的数据读取出来了。

打完收工,在此希望有大神能把我的代码优化一下,或者提供更好的工具类,欢迎斧正。
版权声明:本文为博主原创文章,未经博主允许不得转载。 
http://blog.csdn.net/tavatimsa/article/details/79636817
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息