工具类
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springrain.busi.annotation.ExcelField;
import jxl.Cell;
import jxl.Sheet;
import jxl.SheetSettings;
import jxl.Workbook;
import jxl.format.Alignment;
import jxl.format.Colour;
import jxl.format.UnderlineStyle;
import jxl.format.VerticalAlignment;
import jxl.read.biff.BiffException;
import jxl.write.Label;
import jxl.write.WritableCellFormat;
import jxl.write.WritableFont;
import jxl.write.WritableSheet;
import jxl.write.WritableWorkbook;
/**
* excel操作工具类
*/
public class JxlExcelUtils {
/**
* 根据title导出excel
*
* @param response
* @param columns
* @param list
* @param filename
* @throws Exception
*/
public static void exportToExcelByTitles(HttpServletResponse response, List<String> columns
, List<LinkedHashMap<String, Object>> objData, String filename) throws Exception {
OutputStream os = null;
WritableWorkbook wwb = null;
try {
// 设置弹出对话框
response.setContentType("application/vnd.ms-excel");
// 设置工作表的标题
response.setHeader("Content-Disposition",
"attachment;filename=" + new String(filename.getBytes("gb2312"), "ISO8859-1") + ".xls");// 设置生成的文件名字
// 根据传进来的file对象创建可写入的Excel工作薄
os = response.getOutputStream();
wwb = Workbook.createWorkbook(os);
/*
* 创建一个工作表、sheetName为工作表的名称、"0"为第一个工作表
* 打开Excel的时候会看到左下角默认有3个sheet、"sheet1、sheet2、sheet3"这样 代码中的"0"就是sheet1、其它的一一对应。
* createSheet(sheetName, 0)一个是工作表的名称,另一个是工作表在工作薄中的位置
*/
WritableSheet ws = wwb.createSheet(filename, 0);
ws.setColumnView(1, 30);
// 单元格设置
SheetSettings ss = ws.getSettings();
ss.setVerticalFreeze(1);// 冻结表头
ss.setDefaultColumnWidth(16);// 给sheet电子版中所有的列设置默认的列的宽度;
ss.setShowGridLines(true);
/*
* WritableFont.createFont("宋体"):设置字体为宋体 18:设置字体大小
* WritableFont.BOLD:设置字体加粗(BOLD:加粗 NO_BOLD:不加粗) false:设置非斜体
* UnderlineStyle.NO_UNDERLINE:没有下划线
*/
WritableFont font = new WritableFont(WritableFont.createFont("宋体"), 11, WritableFont.BOLD, false,
UnderlineStyle.NO_UNDERLINE);
WritableCellFormat wcf = new WritableCellFormat(font);
wcf.setBackground(Colour.WHITE);// 背景颜色
wcf.setWrap(true);// 设置自动换行;
wcf.setAlignment(Alignment.CENTRE);// 平行居中
wcf.setVerticalAlignment(VerticalAlignment.CENTRE);// 垂直居中
// 循环写入表头
for (int i = 0; i < columns.size(); i++) {
/*
* 添加单元格(Cell)内容addCell() 添加Label对象Label() 数据的类型有很多种、在这里你需要什么类型就导入什么类型
* 如:jxl.write.DateTime 、jxl.write.Number、jxl.write.Label Label(i, 0,
* columns[i], wcf) 其中i为列、0为行、columns[i]为数据、wcf为样式
* 合起来就是说将columns[i]添加到第一行(行、列下标都是从0开始)第i列、样式为什么"色"内容居中
*/
ws.addCell(new Label(i, 0, columns.get(i), wcf));
}
// 判断表中是否有数据
if (CollectionUtils.isNotEmpty(objData)) {
// 循环写入表中数据
for (int i = 0; i < objData.size(); i++) {
// 转换成map集合{activyName:测试功能,count:2}
Map<String, Object> map = (Map<String, Object>) objData.get(i);
// 循环输出map中的子集:既列值
int j = 0;
for (Object o : map.keySet()) {
// ps:因为要“”通用”“导出功能,所以这里循环的时候不是get("Name"),而是通过map.get(o)
ws.addCell(new Label(j, i + 1, String.valueOf(map.get(o))));
j++;
}
}
}
wwb.write();// 写入Exel工作表
} catch (Exception e) {
e.printStackTrace();
throw new Exception("导出失败");
} finally {
try {
if (null != wwb) {
wwb.close();
}
if (null != os) {
os.flush();
os.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* 读取excel
*
* @param filePath 上传的excel的路径
* @return 返回每行的list集合
* @throws BiffException
*/
public static List<String[]> readExcel(String filePath) throws BiffException {
List<String[]> list = new ArrayList<String[]>();
InputStream stream = null;
Workbook rwb = null;
try {
// 创建输入流
stream = new FileInputStream(filePath);
// 获取Excel文件对象
rwb = Workbook.getWorkbook(stream);
// 获取文件的指定工作表 默认的第一个
Sheet sheet = rwb.getSheet(0);
if (sheet == null || sheet.getRows() == 0) {
return null;
}
// 行数(表头的目录不需要,从1开始)
for (int i = 0; i < sheet.getRows(); i++) {
// 创建一个数组 用来存储每一列的值
String[] str = new String[sheet.getColumns()];
Cell cell = null;
// 列数
for (int j = 0; j < sheet.getColumns(); j++) {
// 获取第i行,第j列的值
cell = sheet.getCell(j, i);
str[j] = cell.getContents();
}
// 把刚获取的列存入list
list.add(str);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (null != rwb) {
rwb.close();
}
if (null != stream) {
stream.close();
}
} catch (Exception e2) {
e2.printStackTrace();
}
}
return list;
}
/**
* 导出excel
*
* @param response
* @param clazz
* @param list
* @param filename
* @param sheetName
* @throws Exception
*/
@SuppressWarnings("rawtypes")
public static void exportToExcel(HttpServletResponse response, Class clazz, List list, String filename) throws Exception {
OutputStream os = null;
WritableWorkbook wwb = null;
try {
// excel表头
List<String> columns = new ArrayList<String>();
LinkedHashMap<String, String> annoFieldMap = getAnnoField(clazz);
for (String value : annoFieldMap.values()) {
columns.add(value);
}
// 数据列表
List<LinkedHashMap<String, Object>> objData = new ArrayList<LinkedHashMap<String, Object>>();
if(CollectionUtils.isEmpty(list)) {
return ;
}
for (int i = 0; i < list.size(); i++) {
Object obj = list.get(i);
Map<String, Object> objFieldMap = getObjFieldKeyAndValue(obj);
LinkedHashMap<String, Object> objDataMap = new LinkedHashMap<String, Object>();
for (Map.Entry<String, String> entry : annoFieldMap.entrySet()) {
if (objFieldMap.get(entry.getKey()) == null || StringUtils.isBlank(objFieldMap.get(entry.getKey()).toString())) {
objDataMap.put(entry.getKey(), "-");
} else {
objDataMap.put(entry.getKey(), objFieldMap.get(entry.getKey()));
}
}
objData.add(objDataMap);
}
// 设置弹出对话框
response.setContentType("application/vnd.ms-excel");
// 设置工作表的标题
response.setHeader("Content-Disposition",
"attachment;filename=" + new String(filename.getBytes("gb2312"), "ISO8859-1") + ".xls");// 设置生成的文件名字
// 根据传进来的file对象创建可写入的Excel工作薄
os = response.getOutputStream();
wwb = Workbook.createWorkbook(os);
/*
* 创建一个工作表、sheetName为工作表的名称、"0"为第一个工作表
* 打开Excel的时候会看到左下角默认有3个sheet、"sheet1、sheet2、sheet3"这样 代码中的"0"就是sheet1、其它的一一对应。
* createSheet(sheetName, 0)一个是工作表的名称,另一个是工作表在工作薄中的位置
*/
WritableSheet ws = wwb.createSheet(filename, 0);
ws.setColumnView(1, 30);
// 单元格设置
SheetSettings ss = ws.getSettings();
ss.setVerticalFreeze(1);// 冻结表头
ss.setDefaultColumnWidth(16);// 给sheet电子版中所有的列设置默认的列的宽度;
ss.setShowGridLines(true);
/*
* WritableFont.createFont("宋体"):设置字体为宋体 18:设置字体大小
* WritableFont.BOLD:设置字体加粗(BOLD:加粗 NO_BOLD:不加粗) false:设置非斜体
* UnderlineStyle.NO_UNDERLINE:没有下划线
*/
WritableFont font = new WritableFont(WritableFont.createFont("宋体"), 11, WritableFont.BOLD, false,
UnderlineStyle.NO_UNDERLINE);
WritableCellFormat wcf = new WritableCellFormat(font);
wcf.setBackground(Colour.WHITE);// 背景颜色
wcf.setWrap(true);// 设置自动换行;
wcf.setAlignment(Alignment.CENTRE);// 平行居中
wcf.setVerticalAlignment(VerticalAlignment.CENTRE);// 垂直居中
// 循环写入表头
for (int i = 0; i < columns.size(); i++) {
/*
* 添加单元格(Cell)内容addCell() 添加Label对象Label() 数据的类型有很多种、在这里你需要什么类型就导入什么类型
* 如:jxl.write.DateTime 、jxl.write.Number、jxl.write.Label Label(i, 0,
* columns[i], wcf) 其中i为列、0为行、columns[i]为数据、wcf为样式
* 合起来就是说将columns[i]添加到第一行(行、列下标都是从0开始)第i列、样式为什么"色"内容居中
*/
ws.addCell(new Label(i, 0, columns.get(i), wcf));
}
// 判断表中是否有数据
if (CollectionUtils.isNotEmpty(objData)) {
// 循环写入表中数据
for (int i = 0; i < objData.size(); i++) {
// 转换成map集合{activyName:测试功能,count:2}
Map<String, Object> map = (Map<String, Object>) objData.get(i);
// 循环输出map中的子集:既列值
int j = 0;
for (Object o : map.keySet()) {
// ps:因为要“”通用”“导出功能,所以这里循环的时候不是get("Name"),而是通过map.get(o)
ws.addCell(new Label(j, i + 1, String.valueOf(map.get(o))));
j++;
}
}
}
wwb.write();// 写入Exel工作表
} catch (Exception e) {
e.printStackTrace();
throw new Exception("导出失败");
} finally {
try {
if (null != wwb) {
wwb.close();
}
if (null != os) {
os.flush();
os.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* 根据对象获取对象key value
*
* @param obj
* @return
* @throws Exception
*/
@SuppressWarnings("rawtypes")
public static Map<String, Object> getObjFieldKeyAndValue(Object obj) throws Exception {
Map<String, Object> map = new HashMap<String, Object>();
Class userCla = (Class) obj.getClass();
Field[] fs = userCla.getDeclaredFields();
for (int i = 0; i < fs.length; i++) {
Field f = fs[i];
f.setAccessible(true);
Object val = f.get(obj);
if (val == null) {
continue;
}
if (f.getName().equals("serialVersionUID")) {
continue;
}
map.put(f.getName(), val);
}
return map;
}
/**
* 根据类获取实体类注解的字段名和注解属性
*
* @param clazz
* @return
*/
@SuppressWarnings("rawtypes")
public static LinkedHashMap<String, String> getAnnoField(Class clazz) throws Exception {
// 获取注解并排序
List<Field> fieldList = new ArrayList<>();
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
if (!field.isAnnotationPresent(ExcelField.class)) {
continue;
}
fieldList.add(field);
}
fieldList.sort(Comparator.comparingInt(m -> m.getAnnotation(ExcelField.class).sort()));
// 将注解放入map中
LinkedHashMap<String, String> valueMap = new LinkedHashMap<>();
for (Field field : fieldList) {
String fieldNames = field.getName();
ExcelField excelField = field.getAnnotation(ExcelField.class);
if (valueMap.get(excelField.name()) != null) {
continue;
}
valueMap.put(fieldNames, excelField.name());
}
return valueMap;
}
}
注解
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 标记可以用于导出excel表头
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface ExcelField {
/**
* 名称
*
* @return
*/
String name() default "";
/**
* 排序
*
* @return
*/
int sort();
}
实体类
@ExcelField(name="本次完成", sort=7)
private java.lang.String currentPlan;
@ExcelField(name="下次计划", sort=8)
private java.lang.String afterPlan;
@ExcelField(name="上次计划", sort=6)
private java.lang.String beforePlan;
使用
JxlExcelUtils.exportToExcel(response, XXX.class, datas, filename);
说明:
1.第一种是根据注解导出excel
2.第二种是传入表头和数据map集合导出数据,根据情况使用