java 导出Excel 大数据量,自己经验总结!(二)

在上一次的基础上加上了样式,以及中文列名

 package com.tommy.fundation.util;

 import java.io.OutputStream;
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 javax.servlet.http.HttpServletResponse; import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFFont;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.IndexedColors; public class ExportExcel<T> {
public void doExcel(HttpServletResponse response, List<T> list, String fileName) throws Exception {
String[] columnNames = new String[0];
doExcel(response, list , columnNames, fileName);
}
/**
* 导出多张excel表,解决xls格式行数65535的限制
* @author OnlyOne
* @param response
* @param list 需要处理的list数据集合
* @param columnNames 与实体属性一一对应的列名
* @param fileName 文件名
* @throws Exception
*/
public void doExcel(HttpServletResponse response, List<T> list, String[] columnNames, String fileName) throws Exception {
OutputStream os = response.getOutputStream();//获取输出流
response.reset();
// 设置下载头部信息。Content-disposition为属性名。attachment表示以附件方式下载,如果要在页面中打开,则改为inline。filename为文件名
response.setContentType("application/vnd.ms-excel;charset=utf-8");
response.setHeader("Content-disposition", "attachment;filename="+ new String((fileName + ".xls").getBytes(), "iso-8859-1")); //将数据集合按65000个进行分割成多个子集合
Map<Integer, List<T>> sheetMap = doSheets(list);
// 创建excel工作簿
HSSFWorkbook wb = new HSSFWorkbook();
//将map集合转换成set集合
Set<Integer> keys = sheetMap.keySet(); // 创建两种单元格格式
HSSFCellStyle cs = wb.createCellStyle();
HSSFCellStyle cs2 = wb.createCellStyle(); // 创建两种字体
HSSFFont f = wb.createFont();
HSSFFont f2 = wb.createFont(); // 创建第一种字体样式(用于列名)
f.setFontHeightInPoints((short) 10);
f.setColor(IndexedColors.BLACK.getIndex());
f.setBoldweight(Font.BOLDWEIGHT_BOLD); // 创建第二种字体样式(用于值)
f2.setFontHeightInPoints((short) 10);
f2.setColor(IndexedColors.BLACK.getIndex()); // 设置第一种单元格的样式(用于列名)
cs.setFont(f);
cs.setBorderLeft(CellStyle.BORDER_THIN);
cs.setBorderRight(CellStyle.BORDER_THIN);
cs.setBorderTop(CellStyle.BORDER_THIN);
cs.setBorderBottom(CellStyle.BORDER_THIN);
cs.setAlignment(CellStyle.ALIGN_CENTER); // 设置第二种单元格的样式(用于值)
cs2.setFont(f2);
cs2.setBorderLeft(CellStyle.BORDER_THIN);
cs2.setBorderRight(CellStyle.BORDER_THIN);
cs2.setBorderTop(CellStyle.BORDER_THIN);
cs2.setBorderBottom(CellStyle.BORDER_THIN);
cs2.setAlignment(CellStyle.ALIGN_CENTER); //对set集合进行遍历
for (Iterator<Integer> iterator = keys.iterator(); iterator.hasNext();) {
//获取遍历的下标
Integer sheetKey = iterator.next();
// 创建一个sheet(页),并命名
HSSFSheet sheet = wb.createSheet("sheet"+sheetKey);
//获取一页的数据
List<T> sheetData = sheetMap.get(sheetKey);
//创建列名的行
HSSFRow firstRow = sheet.createRow(0);
//如果columnNames有值,则作为列名;如果没有,则实体的属性名作为列名
if(columnNames.length == 0){
T en = (T) sheetData.get(0);
List<Object> titleList = RelectUtil.<T>reflectEntityAttribute(en);
for(int m=0; m<titleList.size(); m++){
HSSFCell cell = firstRow.createCell(m);
cell.setCellValue(titleList.get(m+1).toString());
cell.setCellStyle(cs);
}
}else{
for(int m=0; m<columnNames.length; m++){
HSSFCell cell = firstRow.createCell(m);
cell.setCellValue(columnNames[m]);
cell.setCellStyle(cs);
}
} // 手动设置列宽。第一个参数表示要为第几列设;,第二个参数表示列的宽度,n为列高的像素数。
for(int i=0;i<columnNames.length;i++){
sheet.setColumnWidth((short) i, (short) (35.7 * 100));
} //遍历一页的数据集合
for (int i = 0, len = sheetData.size(); i < len; i++) {
//获取数据实体
T en = (T) sheetData.get(i);
//反射获取行数据
List<Object> dataList = RelectUtil.<T>reflectEntity(en, en.getClass());
//创建数据行,以第二行开始,第一行作为列名使用
HSSFRow row = sheet.createRow(i+1);
for(int m=0; m<dataList.size(); m++){
HSSFCell cell = row.createCell(m);
cell.setCellValue(dataList.get(m).toString());
cell.setCellStyle(cs2);
} }
}
wb.write(os);
os.flush();
os.close();
}
/**
* 此方法将数据集合按65000个进行分割成多个子集合
* @author OnlyOne
* @param list 需要处理的list数据集合
* @return
*/
public Map<Integer, List<T>> doSheets(List<T> list){
int count = list.size()/65000;
int yu = list.size() % 65000;
Map<Integer, List<T>> map = new HashMap<Integer, List<T>>();
for (int i = 0; i <= count; i++) {
List<T> subList = new ArrayList<T>();
if (i == count) {
subList = list.subList(i * 65000, 65000 * i + yu);
} else {
subList = list.subList(i * 65000, 65000 * (i + 1));
}
map.put(i, subList);
}
return map;
}
}

辅助工具类

 package com.tommy.fundation.util;

 import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Date;
import java.util.List; public class RelectUtil {
public static <T> List<Object> reflectEntity(T model,Class<?> cals) throws NoSuchMethodException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, SecurityException, NoSuchFieldException{
List<Object> list = new ArrayList<Object>();
Field[] field = model.getClass().getDeclaredFields(); //获取实体类的所有属性,返回Field数组
for(int j=0 ; j<field.length ; j++){ //遍历所有属性
String nam = field[j].getName(); //获取属性的名字
String name = nam;
name = name.substring(0,1).toUpperCase()+name.substring(1);
String type = field[j].getGenericType().toString(); //获取属性的类型 if(type.equals("class java.lang.String")){ //如果type是类类型,则前面包含"class ",后面跟类名
Method m = model.getClass().getMethod("get"+name);
String value = (String) m.invoke(model); //调用getter方法获取属性值
if(value != null){
list.add(value);
}else{
list.add("");
}
} if(type.equals("class java.lang.Integer") || type.equals("int")){
Method m = model.getClass().getMethod("get"+name);
Integer value = (Integer) m.invoke(model);
if(value != null){
list.add(value);
}else{
list.add("");
}
} if(type.equals("class java.lang.Short") || type.equals("short")){
Method m = model.getClass().getMethod("get"+name);
Short value = (Short) m.invoke(model);
if(value != null){
list.add(value);
}else{
list.add("");
}
} if(type.equals("class java.lang.Double") || type.equals("double")){
Method m = model.getClass().getMethod("get"+name);
Double value = (Double) m.invoke(model);
if(value != null){
list.add(value);
}else{
list.add("");
}
} if(type.equals("class java.lang.Boolean") || type.equals("boolean")){
Method m = model.getClass().getMethod("get"+name);
Boolean value = (Boolean) m.invoke(model);
if(value != null){
list.add(value);
}else{
list.add("");
}
} if(type.equals("class java.util.Date")){
Method m = model.getClass().getMethod("get"+name);
Date value = (Date) m.invoke(model);
if(value != null){
list.add(value);
}else{
list.add("");
}
}
}
return list;
}
public static <T> List<Object> reflectEntityAttribute(T model) throws NoSuchMethodException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, SecurityException, NoSuchFieldException {
List<Object> list = new ArrayList<Object>();
Field[] field = model.getClass().getDeclaredFields(); //获取实体类的所有属性,返回Field数组
for (int j = 0; j < field.length; j++) { //遍历所有属性
String nam = field[j].getName(); //获取属性的名字
list.add(nam);
}
return list;
}
}
上一篇:关于call和apply函数的区别及用法


下一篇:只写104行代码!在nopCommerce中如何实现自动生成网站地图