package com.huawei.esysadmin.common.util;
import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRichTextString;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
public class ExportExcel
{
/**
* 利用了JAVA的反射,将javabean的集合以一定的格式输出到指定IO设备上
* @param sheetName
* 工作表标题
* @param headerMap
* 表格列属性及属性名
* @param dataset
* 需要显示的数据集合
* @param out
* 与输出设备相关的流对象,可以将Excel文档导出到本地或者网络中
* @throws IOException
*/
public void exportExcel(String sheetName, Map headerMap, Collection dataset, OutputStream out) throws IOException{
//声明一个工作簿
HSSFWorkbook workbook = new HSSFWorkbook();
//生成一个工作表
HSSFSheet sheet = workbook.createSheet(sheetName);
//设置表格默认列宽
//有些资料在设置宽度的时候用的是short(20),但是在实际使用的过程中,short(20)已不被推荐使用,所以直接使用int(20)
sheet.setDefaultColumnWidth(20);
//获取属性Map的keySet
Set keySet = headerMap.keySet();
//获取属性的数组
String[] fields = keySet.toArray(new String[0]);
//对keySet进行遍历,获得属性对应的属性名称来构成标题行
Iterator key = keySet.iterator();
//第一行
HSSFRow row = sheet.createRow(0);
for(int i = 0; key.hasNext(); i++){
//产生单元格
HSSFCell cell = row.createCell(i);
//产生标题行
HSSFRichTextString title = new HSSFRichTextString(headerMap.get(key.next()));
cell.setCellValue(title);
}
/*
* 遍历数据集合,产生数据行
* 利用反射,通过属性数组来拼接getXXX的方法去获得属性的值
*/
//属性数组的长度
int size = fields.length;
//属性的get方法的数组
String[] methodNames = new String[size];
for(int i = 0; i < size; i++)
{
//拼凑属性的getter方法
methodNames[i] = "get"
+ fields[i].substring(0, 1).toUpperCase()
+ fields[i].substring(1);
}
Iterator ite = dataset.iterator();
for(int index = 1; ite.hasNext(); index++)
{
row = sheet.createRow(index);
T t = (T)ite.next();
for(int i = 0; i < size; i++)
{
HSSFCell cell = row.createCell(i);
try
{
Class> cla = t.getClass();
Method getMethod = cla.getMethod(methodNames[i], new Class[]{});
Object value = getMethod.invoke(t, new Object[]{});
String textValue = null;
//如果属性的类型是String,则直接输出字符串
if(value instanceof String)
{
textValue = value.toString();
}
if(value instanceof Integer || value instanceof Double)
{
textValue = String.valueOf(value);
}
//如果属性的类型是Date,则需要格式转换
if(value instanceof Date)
{
Date date = (Date)value;
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-mm-dd HH:mm:ss");
textValue = sdf.format(date);
}
if(textValue != null)
{
HSSFRichTextString richString = new HSSFRichTextString(textValue);
cell.setCellValue(richString);
}
}catch(Exception e)
{
e.printStackTrace();
}
}
}
//将workbook输出到输出设备中
workbook.write(out);
//关闭资源
out.flush();
workbook.close();
out.close();
}
}
2.1.思路
一般我们导出excel,首先是先查询出一个集合bean,然后使用apache poi 处理数据, 生成excel,此处我们指的是同步导入excel,
异步导入Excel(原始数据组装比较耗时的话)需要使用多线程,此文不讨论.
2.2 代码实现:
1.目标:出学生信息Excel
2.实体类(学生信息)
public class Student implements Serializable
{
private static final long serialVersionUID = 1L;
private String name;
private int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + "]";
}
}
3.Controller类处理
/**
* 导出结果为excel表格
*/
@ResponseBody
@RequestMapping(value = "/exportExcel", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
public BaseResBean exportExcel(@RequestBody ExportAwardReqDto req)
{
BaseResBean res = new BaseResBean();
try {
// Excel导出的查询条件
SearchParamBean searchParamBean = req.getSearchParamBean();
String filename = "学生信息.xls";
HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
.getResponse();
// 设置响应头
response.setContentType("application/vnd.ms-excel;charset=utf-8");
// 设置文件名
response.setHeader("Content-Disposition",
"attachment;filename=\"" + URLEncoder.encode(filename, "UTF-8") + "\" ");
OutputStream out = response.getOutputStream();
// 第一步:获取需要导出的原始数据集合
List dataList = studentService.queryDetail(searchParamBean);
for (Student student : dataList) {
//进行数据组装
asseblemInfo(student);
}
// 第二步:设置excel表头对应的属性值和属性名
Map headerMap = buildExcelHeadMap();
// 第三步:生成excel文件
ExportExcel ex = new ExportExcel();
ex.exportExcel("学生信息", headerMap, dataList, out);
} catch (Exception e)
{
e.printStackTrace();
}
return res;
}
private Map buildExcelHeadMap()
{
Map headerMap = new LinkedHashMap();
headerMap.clear();
headerMap.put("name", "姓名");
headerMap.put("age", "年龄");
return headerMap;
}
//工具类: T为查询的集合的那个bean
public class ExportExcel
{
/**
* 利用了JAVA的反射,将javabean的集合以一定的格式输出到指定IO设备上
* @param sheetName
* 工作表标题
* @param headerMap
* 表格列属性及属性名
* @param dataset
* 需要显示的数据集合
* @param out
* 与输出设备相关的流对象,可以将Excel文档导出到本地或者网络中
* @throws IOException
*/
public void exportExcel(String sheetName, Map headerMap, Collection dataset, OutputStream out) throws IOException{
//声明一个工作簿
HSSFWorkbook workbook = new HSSFWorkbook();
//生成一个工作表
HSSFSheet sheet = workbook.createSheet(sheetName);
//设置表格默认列宽
//有些资料在设置宽度的时候用的是short(20),但是在实际使用的过程中,short(20)已不被推荐使用,所以直接使用int(20)
sheet.setDefaultColumnWidth(20);
//获取属性Map的keySet
Set keySet = headerMap.keySet();
//获取属性的数组
String[] fields = keySet.toArray(new String[0]);
//对keySet进行遍历,获得属性对应的属性名称来构成标题行
Iterator key = keySet.iterator();
//第一行
HSSFRow row = sheet.createRow(0);
for(int i = 0; key.hasNext(); i++){
//产生单元格
HSSFCell cell = row.createCell(i);
//产生标题行
HSSFRichTextString title = new HSSFRichTextString(headerMap.get(key.next()));
cell.setCellValue(title);
}
/*
* 遍历数据集合,产生数据行
* 利用反射,通过属性数组来拼接getXXX的方法去获得属性的值
*/
//属性数组的长度
int size = fields.length;
//属性的get方法的数组
String[] methodNames = new String[size];
for(int i = 0; i < size; i++)
{
//拼凑属性的getter方法
methodNames[i] = "get"
+ fields[i].substring(0, 1).toUpperCase()
+ fields[i].substring(1);
}
Iterator ite = dataset.iterator();
for(int index = 1; ite.hasNext(); index++)
{
row = sheet.createRow(index);
T t = (T)ite.next();
for(int i = 0; i < size; i++)
{
HSSFCell cell = row.createCell(i);
try
{
Class> cla = t.getClass();
Method getMethod = cla.getMethod(methodNames[i], new Class[]{});
Object value = getMethod.invoke(t, new Object[]{});
String textValue = null;
//如果属性的类型是String,则直接输出字符串
if(value instanceof String)
{
textValue = value.toString();
}
if(value instanceof Integer || value instanceof Double)
{
textValue = String.valueOf(value);
}
//如果属性的类型是Date,则需要格式转换
if(value instanceof Date)
{
Date date = (Date)value;
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-mm-dd HH:mm:ss");
textValue = sdf.format(date);
}
if(textValue != null)
{
HSSFRichTextString richString = new HSSFRichTextString(textValue);
cell.setCellValue(richString);
}
}catch(Exception e)
{
e.printStackTrace();
}
}
}
//将workbook输出到输出设备中
workbook.write(out);
//关闭资源
out.flush();
workbook.close();
out.close();
}
}
三.Apache中的poi包中的XSSFWorkbook与HSSFWorkbook的区别:
HSSFWorkbook:是操作Excel2003以前(包括2003)的版本,扩展名是.xls
XSSFWorkbook:是操作Excel2007的版本,扩展名是.xlsx