作为一名底层的JAVA码农,今天领导我分了个烂大街的需求,使用POI做个excel文件的导出。太简单了吧,立马把平时百度的手速拿了出来,翻了一页又一页,demo很多,但是几乎都有bug,最终,我在github拔了好几段靠谱的代码。废话不多说,贴代码:
package com.github.xjs.util;
import com.github.xjs.util.PoiUtil.FieldInfo;
import org.apache.poi.POIXMLException;
import org.apache.poi.hssf.usermodel.HSSFDateUtil;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.poifs.filesystem.OfficeXmlFileException;
import org.apache.poi.ss.usermodel.Cell;
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 java.io.ByteArrayInputStream;
import java.io.IOException;
import java.lang.reflect.Field;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
public class PoiImport {
private static Logger log = LoggerFactory.getLogger(PoiImport.class);
// bytes:筒子们,直接使用这个静态方法,将待上传的excel文件读入成流数组。
// skipNum:自己看着办,从哪一行开始读起
public static <T> List<T> readExcel(String filename, byte[] bytes, Class<T> clazz, int sheetIndex, int skipNum) throws IOException {
List<String[]> arrList = readExcel(filename, bytes, sheetIndex, skipNum);
if (arrList == null || arrList.size() <= 0) {
return null;
}
List<T> list = new ArrayList<T>(arrList.size());
for (String[] arr : arrList) {
T t = stringArrToBean(arr, clazz);
if (t != null) {
list.add(t);
}
}
return list;
}
// 不好意思,太长了,又是抄的,如果想研究,自己慢慢debug
public static List<String[]> readExcel(String filename, byte[] bytes, int sheetIndex, int skipNum) throws IOException {
//获得Workbook工作薄对象
Workbook workbook = null;
try {
workbook = getWorkBook(bytes, filename);
} catch (Exception exception) {//如果人为修改了后缀名
String realFileName = filename;
if (exception instanceof OfficeXmlFileException) {//2007改为了2003
realFileName = filename + "x";
} else if (exception instanceof POIXMLException) {//2003改为了2007
realFileName = filename.substring(0, filename.length() - 1);
} else {
throw new RuntimeException("文件解析异常", exception);
}
if (!filename.equals(realFileName)) {
workbook = getWorkBook(bytes, realFileName);
}
}
//创建返回对象,把每行中的值作为一个数组,所有行作为一个集合返回
List<String[]> list = new ArrayList<String[]>();
//获得sheet工作表
Sheet sheet = workbook.getSheetAt(sheetIndex);
if (sheet == null) {
return null;
}
//获得当前sheet的开始行
int firstRowNum = sheet.getFirstRowNum();
//获得当前sheet的结束行
int lastRowNum = sheet.getLastRowNum();
//循环所有行
while (skipNum-- > 0) {
firstRowNum++;
}
for (int rowNum = firstRowNum; rowNum <= lastRowNum; rowNum++) {
//获得当前行
Row row = sheet.getRow(rowNum);
if (row == null) {
continue;
}
//获得当前行的开始列
int firstCellNum = row.getFirstCellNum();
//获得当前行的列数
int cellNums = row.getPhysicalNumberOfCells();
if (firstCellNum < 0 || cellNums <= 0) {
continue;
}
String[] cells = new String[firstCellNum + cellNums];
//循环当前行
for (int cellNum = firstCellNum; cellNum < firstCellNum + cellNums; cellNum++) {
Cell cell = row.getCell(cellNum);
cells[cellNum] = getCellValue(cell);
}
list.add(cells);
}
return list;
}
private static <T> T stringArrToBean(String[] arr, Class<T> clazz) {
try {
T t = clazz.newInstance();
// 附在后面,自己慢慢看吧,长的很。
List<FieldInfo> fields = PoiUtil.getFiledInfos(clazz);
if (fields == null || fields.size() <= 0) {
return null;
}
for (FieldInfo filed : fields) {
int idx = filed.getOrder();
if (arr.length <= idx) {
continue;
}
fillBeanFieldValue(t, filed, arr[idx]);
}
return t;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private static <T> void fillBeanFieldValue(T bean, FieldInfo filedInfo, String fieldValue) {
if (fieldValue == null || fieldValue.length() <= 0) {
return;
}
try {
Field filed = filedInfo.getFiled();
Class<?> fieldType = filed.getType();
// 这个设置男女性别的方法有点笨,但是哥不想优化
if ("男".equals(fieldValue) || "女".equals(fieldValue)) {
if ("男".equals(fieldValue)) {
filed.set(bean, 1);
} else {
filed.set(bean, 0);
}
} else if (fieldType == String.class) {
filed.set(bean, fieldValue);
} else if (fieldType == int.class) {
filed.set(bean, Integer.valueOf(fieldValue).intValue());
} else if (fieldType == byte.class) {
filed.set(bean, Byte.valueOf(fieldValue).byteValue());
} else if (fieldType == long.class) {
filed.set(bean, Long.valueOf(fieldValue).longValue());
} else if (fieldType == double.class) {
filed.set(bean, Double.valueOf(fieldValue).doubleValue());
} else if (fieldType == boolean.class) {
if ("是".equals(fieldValue) || "Y".equalsIgnoreCase(fieldValue) || "YES".equalsIgnoreCase(fieldValue) || "T".equalsIgnoreCase(fieldValue) || "TRUE".equalsIgnoreCase(fieldValue)) {
filed.set(bean, true);
} else if ("否".equals(fieldValue) || "N".equalsIgnoreCase(fieldValue) || "NO".equalsIgnoreCase(fieldValue) || "F".equalsIgnoreCase(fieldValue) || "FALSE".equalsIgnoreCase(fieldValue)) {
filed.set(bean, false);
}
} else if (fieldType == Integer.class) {
filed.set(bean, Integer.valueOf(fieldValue));
} else if (fieldType == Byte.class) {
filed.set(bean, Byte.valueOf(fieldValue));
} else if (fieldType == Long.class) {
filed.set(bean, Long.valueOf(fieldValue));
} else if (fieldType == Double.class) {
filed.set(bean, Double.valueOf(fieldValue));
} else if (fieldType == Boolean.class) {
if ("是".equals(fieldValue) || "Y".equalsIgnoreCase(fieldValue) || "YES".equalsIgnoreCase(fieldValue) || "T".equalsIgnoreCase(fieldValue) || "TRUE".equalsIgnoreCase(fieldValue)) {
filed.set(bean, Boolean.TRUE);
} else if ("否".equals(fieldValue) || "N".equalsIgnoreCase(fieldValue) || "NO".equalsIgnoreCase(fieldValue) || "F".equalsIgnoreCase(fieldValue) || "FALSE".equalsIgnoreCase(fieldValue)) {
filed.set(bean, Boolean.FALSE);
}
} else if (fieldType == Date.class) {
filed.set(bean, DateUtil.parse(fieldValue, DateUtil.FORMAT_YMD));
} else {
throw new RuntimeException("不支持的数据类型:" + filed.getName() + ":" + fieldType);
}
} catch (Exception e) {
throw new RuntimeException("设置字段值异常:" + bean + "," + filedInfo.getFiled().getName() + ":" + fieldValue, e);
}
}
private static Workbook getWorkBook(byte[] bytes, String fileName) {
try {
fileName = fileName.toLowerCase();
//根据文件后缀名不同(xls和xlsx)获得不同的Workbook实现类对象
if (fileName.endsWith(".xls")) {
//2003
return new HSSFWorkbook(new ByteArrayInputStream(bytes));
} else if (fileName.endsWith(".xlsx")) {
//2007
return new XSSFWorkbook(new ByteArrayInputStream(bytes));
} else {
throw new RuntimeException("文件后缀名不合法");
}
} catch (IOException e) {
log.error(e.getMessage(), e);
throw new RuntimeException(e);
}
}
private static String getCellValue(Cell cell) {
String cellValue = "";
if (cell == null) {
return cellValue;
}
switch (cell.getCellType()) {
case Cell.CELL_TYPE_NUMERIC: //数字
// 特么的超级坑,Java将日期读成数字,老子花了会功夫才解决这个问题。
// 避免将日期读成数字
if (HSSFDateUtil.isCellDateFormatted(cell)) {
Date date = cell.getDateCellValue();
String value = new SimpleDateFormat("yyyy-MM-dd").format(date);
return value;
}
//把数字当成String来读,避免出现1读成1.0的情况
cell.setCellType(Cell.CELL_TYPE_STRING);
// cellValue = String.valueOf(cell.getNumericCellValue());
cellValue = String.valueOf(cell.getStringCellValue());
break;
case Cell.CELL_TYPE_STRING: //字符串
cellValue = String.valueOf(cell.getStringCellValue());
break;
case Cell.CELL_TYPE_BOOLEAN: //Boolean
cellValue = String.valueOf(cell.getBooleanCellValue());
break;
case Cell.CELL_TYPE_FORMULA: //公式
cellValue = String.valueOf(cell.getCellFormula());
break;
case Cell.CELL_TYPE_BLANK: //空值
cellValue = "";
break;
case Cell.CELL_TYPE_ERROR: //故障
cellValue = "非法字符";
break;
default:
cellValue = "未知类型";
break;
}
return cellValue;
}
// public static void main(String[] args) throws Exception {
//
// InputStream in = new FileInputStream("E:" + File.separator + "xxxx.xlsx");
// byte[] bytes = IOUtil.readInputStream(in);
// List<PatientInfo> infos = readExcel("xxxx.xlsx", bytes, PatientInfo.class, 0, 3);
// if (in != null) {
// in.close();
// }
//
// }
}
不好意思,以下完全是大牛的代码,作为程序员,重复造轮子是大忌,所以直接贴给大家了,顺便跟大家说说,github真的有很多优秀的大牛代码。
package com.github.xjs.util;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.URLEncoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import javax.servlet.http.HttpServletResponse;
/**
* @author xujs@inspur
*
* @date 2017年8月16日 下午2:1:12
*/
public class PoiUtil {
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public static @interface FiledOrder{
public int value();//从0开始
}
public interface FieldSerializer<T,V>{
public String serialize(T bean, V fieldValue);
}
public static abstract class FieldNameSerializer<T, V> implements FieldSerializer<T,V> {
private String fieldName;
public FieldNameSerializer(String fieldName) {
this.fieldName = fieldName;
}
public String getFieldName() {
return this.fieldName;
}
}
public static abstract class FieldTypeSerializer<T, V> implements FieldSerializer<T,V> {
private Class<V> fieldType;
public FieldTypeSerializer(Class<V> clazz) {
this.fieldType = clazz;
}
public Class<V> getFieldType(){
return this.fieldType;
}
}
public static <T> List<T> readExcel(String filename, byte[] bytes,Class<T> clazz) throws IOException{
return PoiImport.readExcel(filename, bytes, clazz, 0, true);
}
public static <T> List<T> readExcel(String filename, byte[] bytes,Class<T> clazz, int sheetIndex) throws IOException{
return PoiImport.readExcel(filename, bytes, clazz, sheetIndex, true);
}
public static <T> List<T> readExcel(String filename, byte[] bytes,Class<T> clazz, int sheetIndex, boolean skipFirst) throws IOException{
return PoiImport.readExcel(filename, bytes, clazz, sheetIndex, skipFirst);
}
public static <T,V> byte[] writeExcel(List<T> datas) throws Exception{
return writeExcel((List<String>)null, datas, (List<FieldSerializer<T,V>>)null);
}
public static <T,V> byte[] writeExcel(String[] heads, List<T> datas) throws Exception{
return writeExcel(heads==null?(List<String>)null:Arrays.asList(heads), datas, (List<FieldSerializer<T,V>>)null);
}
public static <T,V> byte[] writeExcel(List<String> heads, List<T> datas) throws Exception{
return writeExcel(heads, datas, (List<FieldSerializer<T,V>>)null);
}
@SafeVarargs
public static <T, V> byte[] writeExcel(String[] heads, List<T> datas, FieldSerializer<T,V>... serializers) throws Exception{
return writeExcel(heads==null?(List<String>)null:Arrays.asList(heads), datas, serializers==null?(List<FieldSerializer<T,V>>)null:Arrays.asList(serializers));
}
@SafeVarargs
public static <T, V> byte[] writeExcel(List<String> heads, List<T> datas, FieldSerializer<T,V>... serializers) throws Exception{
return writeExcel(heads, datas, serializers==null?(List<FieldSerializer<T,V>>)null:Arrays.asList(serializers));
}
public static <T, V> byte[] writeExcel(String[] heads, List<T> datas, List<FieldSerializer<T,V>> serializers) throws Exception{
return writeExcel(heads==null?(List<String>)null:Arrays.asList(heads), datas, serializers);
}
public static <T,V> byte[] writeExcel(List<String> heads, List<T> datas, List<FieldSerializer<T,V>> serializers) throws Exception{
PoiExport pe = new PoiExport();
pe.registerFormatters(serializers);
return pe.writeExcel(heads, datas);
}
public static <T,V> void downloadExcel(HttpServletResponse response, String filename, List<T> dataset) throws Exception {
downloadExcel(response, filename, (List<String>)null, dataset, (List<FieldSerializer<T,V>>)null);
}
public static <T,V> void downloadExcel(HttpServletResponse response, String filename, String[] headers, List<T> dataset) throws Exception {
downloadExcel(response, filename, headers==null?null:Arrays.asList(headers), dataset, (List<FieldSerializer<T,V>>)null);
}
public static <T,V> void downloadExcel(HttpServletResponse response, String filename, List<String> headers, List<T> dataset) throws Exception {
downloadExcel(response, filename, headers, dataset, (List<FieldSerializer<T,V>>)null);
}
@SafeVarargs
public static <T,V> void downloadExcel(HttpServletResponse response, String filename, String[] headers, List<T> dataset,FieldSerializer<T,V>... serializers) throws Exception {
downloadExcel(response, filename, headers==null?null:Arrays.asList(headers), dataset, serializers==null?(List<FieldSerializer<T,V>>)null:Arrays.asList(serializers));
}
@SafeVarargs
public static <T,V> void downloadExcel(HttpServletResponse response, String filename, List<String> headers, List<T> dataset,FieldSerializer<T,V>... serializers) throws Exception {
downloadExcel(response, filename, headers, dataset, serializers==null?null:Arrays.asList(serializers));
}
public static <T,V> void downloadExcel(HttpServletResponse response, String filename, String[] headers, List<T> dataset,List<FieldSerializer<T,V>> serializers) throws Exception {
downloadExcel(response, filename, headers==null?null:Arrays.asList(headers), dataset, serializers);
}
public static <T,V> void downloadExcel(HttpServletResponse response, String filename,List<String> headers, List<T> dataset, List<FieldSerializer<T,V>> serializers) throws Exception {
//设置文件ContentType类型,这样设置,会自动判断下载文件类型
response.setContentType("multipart/form-data;charset=UTF-8");
//设置文件头:最后一个参数是设置下载文件名
response.setHeader("Content-Disposition", "attachment;fileName="+ URLEncoder.encode(filename, "UTF-8"));
byte[] bytes = writeExcel(headers, dataset, serializers);
OutputStream out = response.getOutputStream();
out.write(bytes);
out.flush();
}
private static ConcurrentHashMap<Class<?>, List<FieldInfo>> fieldInfoCache = new ConcurrentHashMap<Class<?>, List<FieldInfo>>();
public static class FieldInfo{
private Field filed;
private int order;
public FieldInfo(Field filed, int order) {
super();
this.filed = filed;
this.order = order;
}
public Field getFiled() {
return filed;
}
public void setFiled(Field filed) {
this.filed = filed;
}
public int getOrder() {
return order;
}
public void setOrder(int order) {
this.order = order;
}
}
public static List<FieldInfo> getFiledInfos(Class<?> clazz){
List<FieldInfo> list = fieldInfoCache.get(clazz);
if(list != null && list.size() > 0) {
return list;
}
List<FieldInfo> fieldInfos = new ArrayList<FieldInfo>();
Class<?> targetClass = clazz;
do {
Field[] fields = targetClass.getDeclaredFields();
for (Field field : fields) {
if((Modifier.isStatic(field.getModifiers()) || Modifier.isFinal(field.getModifiers()))){
continue;
}
field.setAccessible(true);
FiledOrder orderAnno = field.getAnnotation(FiledOrder.class);
if(orderAnno == null) {
continue;
}
fieldInfos.add(new FieldInfo(field, orderAnno.value()));
}
targetClass = targetClass.getSuperclass();
} while (targetClass != null && targetClass != Object.class);
Collections.sort(fieldInfos, new Comparator<FieldInfo>() {
@Override
public int compare(FieldInfo o1, FieldInfo o2) {
return o1.getOrder()-o2.getOrder();
}
});
fieldInfoCache.putIfAbsent(clazz, fieldInfos);
return fieldInfos;
}
// 以下是TEST
public static class User{//不用遵守javabean规范
@FiledOrder(0)
private int id;
@FiledOrder(1)
private String name;
@FiledOrder(2)
private Date birthDay;
@FiledOrder(3)
private boolean isMale;
public User() {}
public User(int id, String name, Date birthDay, boolean isMale) {
this.id = id;
this.name = name;
this.birthDay = birthDay;
this.isMale = isMale;
}
@Override
public String toString() {
return "User [id=" + id + ", name=" + name + ", birthDay=" + birthDay + ", isMale=" + isMale + "]";
}
}
public static void main(String args[])throws Exception {
String file = "C:\\Users\\xujs\\Desktop\\aa.xls";
User user1 = new User(1, "aaa", new Date(), true);
User user2 = new User(2, "bbb", new Date(), false);
User user3 = new User(3, "ccc", new Date(), true);
User user4 = new User(4, "ddd", new Date(), false);
List<User> users = new ArrayList<User>(4);
users.add(user1);users.add(user2);users.add(user3);users.add(user4);
FieldSerializer<User, Boolean> serializer = new FieldNameSerializer<User, Boolean>("isMale") {
@Override
public String serialize(User bean, Boolean fieldValue) {
if(fieldValue) {
return "是";
}else {
return "否";
}
}
};
byte[] bytes = writeExcel(new String[] {"id","姓名","生日","是否男性"}, users, serializer);
OutputStream out = new FileOutputStream(file);
out.write(bytes);
out.close();
System.out.println("write over");
InputStream in = new FileInputStream(file);
bytes = IOUtil.readInputStream(in);
in.close();
List<User> list = readExcel(file,bytes, User.class);
System.out.println(list.size());
for(User u : list) {
System.out.println(u);
}
System.out.println("read over");
}
}
更多推荐
JAVA 使用POI 上传 excel文件
发布评论