package com.smp.poi.utils;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Set;
import org.apache.commons.lang.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
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.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import reactor.util.CollectionUtils;
public class DBToExcelUtil {
private static final String poiCode = "poiCode";
private final static Logger logger = LoggerFactory.getLogger(DBToExcelUtil.class);
/**
* 将List中的数据输入新建的excel中
*
* @param <T>
* @param retList
* 需输入excel数据 此数据库查询结果类型,使用LinkedHashMap会按照数据库表字段顺序取出相应字段
* @param excelPath
* excel的位置与名称 如:D://用户表.xls
* @param sheetName
* excel中sheet名称
* @param title
* Map<String,String>,key为数据库字段名,value为应该显示的名称
* @param width
* 1=1/256charactor
* @return 存入excel信息说明
*/
public static <T> HashMap<String, String> listToNewExcelc(List<T> retList, String excelPath, String sheetName,
LinkedHashMap<String, String> title, int width) throws Exception {
logger.info("入参如下:表数据:{},导出路径:{},sheet名称:{},标头:{},每个单元格的宽度:{}", retList, excelPath, sheetName, title, width);
// 1.校验
HashMap<String, String> poiCode = validate(retList, excelPath, sheetName);
// 2.如果校验不通过 则直接返回错误码
if (!CollectionUtils.isEmpty(poiCode)) {
return poiCode;
}
// 3.定义工作薄
Workbook workbook = null;
if (excelPath.endsWith(".xls")) {
// 声明一个.xls工作薄
workbook = new HSSFWorkbook();
} else if (excelPath.endsWith(".xlsx")) {
// 声明一个.xlsx工作薄
workbook = new XSSFWorkbook();
} else {
poiCode.put(DBToExcelUtil.poiCode, "数据文件格式定义错误!");
return poiCode;
}
// 4.設置sheet
setSheet(workbook, sheetName);
// 5.设置标头
setHeadContent(workbook, title, width);
// 6.设置表中数据
setBodyContent(retList, workbook.getSheetAt(0), title);
// 7.将excel输出到给定的路径下,并生成文件
return dataToExcel(workbook, poiCode, excelPath);
}
/**
* 将excel数据根据给的路径生成相应的excel文件
*
* @param workbook
* @param poiCode
* @param excelPath
* @return
*/
public static HashMap<String, String> dataToExcel(Workbook workbook, HashMap<String, String> poiCode,
String excelPath) {
FileOutputStream fileStream = null;
try {
// 获取输出文件流
fileStream = new FileOutputStream(excelPath);
// 写入数据
workbook.write(fileStream);
poiCode.put(DBToExcelUtil.poiCode, "导出成功");
logger.info("导出成功");
} catch (FileNotFoundException e) {
poiCode.put(DBToExcelUtil.poiCode, "没有找到文件");
logger.info("没有找到文件");
} catch (IOException e) {
poiCode.put(DBToExcelUtil.poiCode, "文件导出失败");
logger.info("文件导出失败");
} finally {
// 关闭资源
if (fileStream != null) {
try {
fileStream.close();
} catch (IOException e) {
logger.info("关闭资源时发生异常,异常如下:{}", e);
}
}
}
return poiCode;
}
/**
* 設置表中的数据内容
*
* @param retList
* @param sheet
* @param title
* @throws Exception
*/
public static <T> void setBodyContent(List<T> retList, Sheet sheet, LinkedHashMap<String, String> title)
throws Exception {
Set<String> demokeys = title.keySet();
String[] sheetHander = demokeys.toArray(new String[0]);
// 设置表的内容
for (int i = 0; i < retList.size(); i++) {
// 设置第i+1行内容
Row rowBody = sheet.createRow(i + 1);
// 获取第i行数据
T db = retList.get(i);
for (int j = 0; j < sheetHander.length; j++) {
// 设置第i+1行第j列数据
Cell c = rowBody.createCell(j);
c.setCellValue(String.valueOf(getValByName(sheetHander[j], db)));
}
}
}
/**
* 设置标头
*
* @param workbookTemp
* @param title
* @param width
* @return
*/
public static Workbook setHeadContent(Workbook workbookTemp, LinkedHashMap<String, String> title, int width) {
// 获取第一个sheet的第一行
Sheet sheet = workbookTemp.getSheetAt(0);
Row rowHeader = sheet.createRow(0);
// 定义表头的字段
Set<String> demokeys = title.keySet();
String[] sheetHander = demokeys.toArray(new String[0]);
// 设置表头字段
for (int i = 0; i < sheetHander.length; i++) {
// 获取表头第i列对象
Cell cell = rowHeader.createCell(i);
// 设置列对象的内容
cell.setCellValue(title.get(sheetHander[i]));
// 每一列宽度均设置为15
sheet.setColumnWidth(i, width);
}
return workbookTemp;
}
/**
* 根据字段名字获取所对应的值 反射
*
* @param key
* @param db
* @return
* @throws Exception
*/
public static <T> Object getValByName(String key, T db) {
String getter = "get" + key.substring(0, 1).toUpperCase() + key.substring(1);
Method m;
try {
m = db.getClass().getMethod(getter, null);
try {
if (m.invoke(db, null) != null) {
return m.invoke(db, null);
} else {
return "";
}
} catch (Exception e) {
logger.error("获取类的字段值的时候发生了异常,异常如下:{}", e);
return "";
}
} catch (Exception e) {
logger.error("获取类的字段值的时候发生了异常,异常如下:{}", e);
return "";
}
}
/**
* 设置sheet格式
*
* @param workbook
* @param sheetName
* @return
*/
public static Workbook setSheet(Workbook workbook, String sheetName) {
// 声明一个sheet并命名
Sheet sheet = workbook.createSheet(sheetName);
// 给单子名称一个长度
sheet.setDefaultColumnWidth(15);
// 生成一个样式
CellStyle style = workbook.createCellStyle();
// 样式字体居中
style.setAlignment(CellStyle.ALIGN_LEFT);
return workbook;
}
/**
* 校验
*
* @param retList
* @param poiCode
* @param excelPath
* @param sheetName
* @return
*/
public static <T> HashMap<String, String> validate(List<T> retList, String excelPath, String sheetName) {
HashMap<String, String> poiCode = new HashMap<String, String>();
if (CollectionUtils.isEmpty(retList)) {
poiCode.put(DBToExcelUtil.poiCode, "存入数据为空");
logger.error("存入数据为空");
return poiCode;
}
if (StringUtils.isEmpty(excelPath)) {
poiCode.put(DBToExcelUtil.poiCode, "Excel路径为空");
logger.error("Excel路径为空");
return poiCode;
}
if (StringUtils.isEmpty(sheetName)) {
poiCode.put(DBToExcelUtil.poiCode, "Sheet名为空");
logger.error("Sheet名为空");
return poiCode;
}
if (!excelPath.endsWith(".xls") && !excelPath.endsWith(".xlsx")) {
poiCode.put(DBToExcelUtil.poiCode, "此文件不是excel类型");
logger.error("此文件不是excel类型");
return poiCode;
}
return poiCode;
}
/**
* 准备excel的标题栏
*
* @return
*/
public static <T> LinkedHashMap<String, String> prepareTitle(Class<T> clazz) {
LinkedHashMap<String, String> title = new LinkedHashMap<String, String>();
Field[] fields = clazz.getDeclaredFields();
for (Field o : fields) {
title.put(String.valueOf(o.getName()), String.valueOf(o.getName()));
}
return title;
}
}