java web项目中时常会用到导出功能,而导出excel几乎是每个项目必备的功能之一。针对形形色色的导出方法及个人平时的工作经验,特将导出excel方法整理成通用的方法,根据xml配置来实现特定的导出。

  此方法基于struts2框架实现,先看struts.xml配置文件中的配置方法:

 <action name="exportExcel" class="exportExcelAction">
<result name="download" type="stream">
<param name="contentType">application/vnd.ms-excel</param>
<param name="contentDisposition">attachment;filename="${excelName}"</param>
<param name="inputName">excelStream</param>
</result>
</action>

  1、excelName对应bean中的excelName属性,为导出文件名称;

  2、excelStream对应bean中导出数据流,即导出方法返回的数据流。

  接着是导出配置文件:excel.xml,需要导出的列表按照规则配置在此xml文件中即可:

 <?xml version="1.0" encoding="utf-8"?>
<excel>
<element title="检测库信息表" class="com.model.CheckRecord">
<property name="xmmc" display_name="项目名称"></property>
<property name="sampleNo" display_name="样品编号"></property>
<property name="detectTime" display_name="检测日期"></property>
<property name="jcbh" display_name="检测板号"></property>
<property name="ypmc" display_name="样品名称"></property>
<property name="yplx" display_name="样品类型"></property>
<property name="ypcd" display_name="样品产地"></property>
<property name="resultType" display_name="检测类型"></property>
<property name="resultValue" display_name="检测结果"></property>
<property name="resultDetect" display_name="检测读数值"></property>
<property name="resultTip" display_name="检测提示"></property>
<property name="submitStaff" display_name="送检人员"></property>
<property name="submitTime" display_name="送检时间"></property>
</element>
</excel>

  excel节点为根节点,element节点即为需要导出的列表节点,class属性用来唯一区别不同的导出列表,即根据class属性查找需要导出的列表属性集合,title属性当然是导出excel表格的标题咯。

  property节点是需要导出的字段,name属性和javabean中属性一一对应,display_name是excel表格所对应的显示名称。

  不同的导出列表只需要按照上面的实例配置多个element即可,切记class属性要唯一哦。

  接下来就是导出excel工具类啦,先看代码:

 package excel.util;

 /**
* 导出excel工具类
* @author BaiFL
*/
public class ExportExcelUtil { /**标题**/
private String title; private InputStream inputStream = null; private ByteArrayOutputStream outputStream = null; private HSSFWorkbook workbook; private HSSFSheet sheet; /**表格行**/
private HSSFRow row; /**单元格**/
private HSSFCell cell; /**字体**/
private HSSFFont font; /**单元格样式**/
private HSSFCellStyle cellStyle; /**
* 字段及字段注释
* key:字段名
* value:字段注释
*/
private Map<String, String> propertyMap = new HashMap<String, String>(); /**
* 导出excel
* @param className 完整类名
* @param list 导出结果集
*/
public InputStream export(String className, List<?> list){ //初始化
this.instance(className); //设置字体
font = workbook.createFont();
font.setFontName("宋体");
font.setFontHeightInPoints((short) 12); //设置单元格类型
cellStyle = workbook.createCellStyle();
cellStyle.setFont(font);
cellStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER); //创建第一行title
row = sheet.createRow(0);
this.setCellValue(0, title);
//合并单元格:0行~0行,0列~propertyMap.size() - 1列
sheet.addMergedRegion(new CellRangeAddress(0, 0, 0, propertyMap.size() - 1)); //创建第二行标题行
row = sheet.createRow(1);
int i = 0;
//遍历propertyMap
for(String key : propertyMap.keySet()){
//创建单元格
this.setCellValue(i, propertyMap.get(key));
i++;
} //遍历数据集合
for(int j = 0; j < list.size(); j++) {
Object object = list.get(j);
//创建数据行,从第三行开始
row = sheet.createRow(j + 2);
int k = 0;
for(String key : propertyMap.keySet()){
Field f;
String value;
try {
f = object.getClass().getDeclaredField(key);
//设置私有字段的可访问性
f.setAccessible(true);
//获取字段get方法
value = String.valueOf(f.get(object));
//设置单元格
this.setCellValue(k, value);
k++;
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
}
try {
outputStream = new ByteArrayOutputStream();
workbook.write(outputStream);
byte[] content = outputStream.toByteArray();
inputStream = new ByteArrayInputStream(content);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
try {
if(outputStream != null){
outputStream.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
return inputStream;
} /**
* 初始化
* @param className 完整类名
* 根据className获取excel.xml文件对应element属性集合
*/
@SuppressWarnings("unchecked")
private void instance(String className){
//加载配置文件
inputStream = ExportExcelUtil.class.
getResourceAsStream("/resources/exportExcel/excel.xml"); this.workbook = new HSSFWorkbook();
this.sheet = workbook.createSheet(); SAXReader reader = new SAXReader(); Document document = null;
try {
document = reader.read(inputStream);
} catch (DocumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} //获取根节点
Element excel = document.getRootElement(); //获取element集合
List<Element> elementList = excel.elements("element");
//根据class属性获取对应导出字段属性集合
for(Element element : elementList){
if(className.equals(element.attributeValue("class"))){
title = element.attributeValue("title");
//element下所有property集合
List<Element> childList = element.elements();
for(Element child : childList){
propertyMap.put(child.attributeValue("name"),
child.attributeValue("display_name"));
}
}
}
} /**
* 设置单元格
* @param index
* @param value
*/
private void setCellValue(int index, String value){
//创建单元格,设置单元格属性为文本类型
cell = row.createCell(index, HSSFCell.CELL_TYPE_STRING);
cell.setCellStyle(cellStyle);
cell.setCellValue(value);
//设置第index列宽为自动
sheet.autoSizeColumn(index);
} }
   方法export(String className, List<?> list)即导出excel通用方法,参数1:className对应导出配置文件excel.xml文件中element节点的class属 性,为完整类名;参数2:list即需要导出的数据,该list为对象集合,非数组集合。

  下面就是action中如何用啦,前面所有工作做好以后action中只需要很少的代码调用就可以啦,先看代码:
     /**
* exportExcel
* @return
*/
public String exportExcel() {
//获取数据条数
int count = recordService.count(checkRecord);
//分页
Page page = listForm.getPageObj(count);
if(StringUtils.blank(page.getOrderBy())){
//默认按检测时间倒序排序
page.setOrderBy("detectTime");
page.setOrder("desc");
}
//导出excel
if(Constant.EXPORT.equals(export)){
page.setPage(0);
page.setPageSize(exportSize !=0 && exportSize < count ? exportSize : (count < 65535 ? count : 65535));
List<CheckRecord> list = recordService.find(checkRecord, page);
excelStream = excel.export(CheckRecord.class.getName(), list);
return "download";  
}else{
List<CheckRecord> list = recordService.find(checkRecord, page);
httpServletRequest.setAttribute("List", list);
httpServletRequest.setAttribute("Page", page);
return "list";
}
}

  这是普通的页面列表数据展示代码,当属性export值为Constant.EXPORT("export")时,执行导出excel操作,导出数据范围为exportSize~65535;

  action中还必须有excelStream、excelName两个属性,分别和struts中的属性一一对应。

  /**导出excel数据流对应struts中的stream**/
  protected InputStream excelStream;

  /**excel文件名**/
  protected String excelName;

  getter/setter方法这里就不写了,action中可一定要写哦。

  至此,整个导出功能全部实现,赶紧试试吧

  下面的代码无需配置struts,直接导出并下载:

 package com.jeecms.common.util;

 import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map; import javax.servlet.http.HttpServletResponse; import org.apache.poi.hssf.usermodel.HSSFCell;
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.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.util.CellRangeAddress;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader; /**
* 导出excel工具类
* @author BaiFL
*/
public class ExportExcelUtil { /**标题**/
private String title; private InputStream inputStream = null; private OutputStream os = null; private HSSFWorkbook workbook; private HSSFSheet sheet; /**表格行**/
private HSSFRow row; /**单元格**/
private HSSFCell cell; /**字体**/
private HSSFFont font; /**单元格样式**/
private HSSFCellStyle cellStyle; /**
* 字段及字段注释
* key:字段名
* value:字段注释
*/
private Map<String, String> propertyMap = new LinkedHashMap<String, String>(); /**
* 导出excel
* @param className 完整类名
* @param list 导出结果集
* @param response
*/
public void export(String className, List<?> list, HttpServletResponse response){ //初始化
this.instance(className); response.reset(); response.setCharacterEncoding("UTF-8");
response.setContentType("application/vnd.ms-excel");
String fileName = null;
try {
fileName = new String(title.getBytes("GBK"), "ISO-8859-1");
} catch (UnsupportedEncodingException e1) {
e1.printStackTrace();
}
response.setHeader("Content-Disposition", "filename=" + fileName + DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss")+ ".xls"); //设置字体
font = workbook.createFont();
font.setFontName("宋体");
font.setFontHeightInPoints((short) 12); //设置单元格类型
cellStyle = workbook.createCellStyle();
cellStyle.setFont(font);
cellStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER); //创建第一行title
row = sheet.createRow(0);
this.setCellValue(0, title);
//合并单元格:0行~0行,0列~propertyMap.size() - 1列
sheet.addMergedRegion(new CellRangeAddress(0, 0, 0, propertyMap.size() - 1)); //创建第二行标题行
row = sheet.createRow(1);
int i = 0;
//遍历propertyMap
for(String key : propertyMap.keySet()){
//创建单元格
this.setCellValue(i, propertyMap.get(key));
i++;
}
//遍历数据集合
for(int j = 0; j < list.size(); j++) {
Object object = list.get(j);
//创建数据行,从第三行开始
row = sheet.createRow(j + 2);
int k = 0;
for(String key : propertyMap.keySet()){
if(key.indexOf(".") > 0){ //关联对象中的私有属性
String[] keyArr = key.split("\\.");
Field field;
Object obj = object;
for(int t = 0; t < keyArr.length; t++){
if(t + 1 == keyArr.length){ //获取私有字段值
try {
field = obj.getClass().getDeclaredField(keyArr[t]);
//设置私有字段的可访问性
field.setAccessible(true);
//获取字段get方法
Object value = field.get(obj);
//设置单元格
this.setCellValue(k, (value == null ? "" : String.valueOf(value)));
k++;
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}else{ //获取关联对象
try {
field = obj.getClass().getDeclaredField(keyArr[t]);
//设置私有字段的可访问性
field.setAccessible(true);
//获取字段get方法
obj = field.get(obj);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}else{ //不包含关联对象的私有属性
try {
Field f = object.getClass().getDeclaredField(key);
//设置私有字段的可访问性
f.setAccessible(true);
//获取字段get方法
Object value = f.get(object);
//设置单元格
this.setCellValue(k, (value == null ? "" : String.valueOf(value)));
k++;
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
}
}
try {
os = response.getOutputStream();
workbook.write(os);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
try {
if(os != null){
os.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
} /**
* 初始化
* @param className 完整类名
* 根据className获取excel.xml文件对应element属性集合
*/
@SuppressWarnings("unchecked")
private void instance(String className){
//加载配置文件
inputStream = ExportExcelUtil.class.getResourceAsStream("/resources/exportExcel/excel.xml"); SAXReader reader = new SAXReader(); Document document = null;
try {
document = reader.read(inputStream);
} catch (DocumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} //获取根节点
Element excel = document.getRootElement(); //获取element集合
List<Element> elementList = excel.elements("element");
//根据class属性获取对应导出字段属性集合
for(Element element : elementList){
if(className.equals(element.attributeValue("class"))){
title = element.attributeValue("title");
//element下所有property集合
List<Element> childList = element.elements();
for(Element child : childList){
propertyMap.put(child.attributeValue("name"), child.attributeValue("display_name"));
}
}
} this.workbook = new HSSFWorkbook();
this.sheet = workbook.createSheet(title);
} /**
* 设置单元格
* @param index
* @param value
*/
private void setCellValue(int index, String value){
//创建单元格,设置单元格属性为文本类型
cell = row.createCell(index, HSSFCell.CELL_TYPE_STRING);
cell.setCellStyle(cellStyle);
cell.setCellValue(value);
//设置第index列宽为自动
sheet.autoSizeColumn(index);
} }

action中使用方法:

     /**
* 导出
* @param queryValue
* @param pageNo
* @param request
* @param response
* @param model
*/
@RequestMapping(value = "/addresslist/export.do")
public void export(String queryValue, Integer pageNo,
HttpServletRequest request, HttpServletResponse response, ModelMap model) {
List<CmsUser> list = manager.getExcelList(CmsUtils.getSiteId(request), queryValue);
ExportExcelUtil excel = new ExportExcelUtil();
excel.export(CmsUser.class.getName(), list, response);
log.info("通讯录导出成功!");
}
 
												

java根据xml配置文件导出excel通用方法的更多相关文章

  1. java导出excel通用方法

    首先需要引入的jar包: 正式代码了. import java.io.FileOutputStream; import java.io.OutputStream; import java.net.UR ...

  2. NOPI 导出excel 通用方法

    public static byte[] ExportExcel<T>(Dictionary<string, string> columnsHeader, List<T& ...

  3. NPOI 导出excel 通用方法

    public static byte[] ExportExcel<T>(Dictionary<string, string> columnsHeader, List<T& ...

  4. NPOI导入导出EXCEL通用类,供参考,可直接使用在WinForm项目中

    以下是NPOI导入导出EXCEL通用类,是在别人的代码上进行优化的,兼容xls与xlsx文件格式,供参考,可直接使用在WinForm项目中,由于XSSFWorkbook类型的Write方法限制,Wri ...

  5. ASP.NET导出excel表方法汇总

    asp.net里导出excel表方法汇总  1.由dataset生成 public void CreateExcel(DataSet ds,string typeid,string FileName) ...

  6. XML格式导出Excel

    下面介绍一种导出Excel的方法: 此方法不需要在服务器上安装Excel,采用生成xml以excel方式输出到客户端,可能需要客户机安装excel,所以也不会有乱七八糟的权限设定,和莫名其妙的版本问题 ...

  7. Java中导入、导出Excel

    原文:Java中导入.导出Excel 一.介绍 当前B/S模式已成为应用开发的主流,而在企业办公系统中,常常有客户这样子要求:你要把我们的报表直接用Excel打开(电信系统.银行系统).或者是:我们已 ...

  8. 懒人小工具:T4自动生成Model,Insert,Select,Delete以及导出Excel的方法

    之前写了篇文章,懒人小工具:[自动生成Model,Insert,Select,Delete以及导出Excel的方法](http://www.jianshu.com/p/d5b11589174a),但是 ...

  9. java使用poi生成导出Excel(新)

    导出样式: java代码: import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStre ...

随机推荐

  1. [React] Use the URL as the source of truth in React

    In Single Page Apps we're used to fetch the data on event callbacks. That disables the capacity to u ...

  2. 在web开发中你不得不注意的安全验证问题#2-XSS

    前言 XSS又叫CSS (Cross Site Script) ,跨站脚本攻击. 恶意攻击者往Web页面里插入恶意html代码.当用户浏览该页之时,嵌入当中Web里面的html代码会被运行,从而达到恶 ...

  3. eclipse-ubuntu14.04图标替换不掉的问题

    今天安装14.04的时候,遇到了一个问题.就是eclipse安装好以后,发现需要配置ADT,老是配置失败.后来实在没有办法了,所以就把这个eclipse跟删除了(当时它并没有安装,而是仅仅解压以后双击 ...

  4. DG观察日志传输

    --primary端查询v$archived_log视图,确认日志是否被应用:   set lines 300 pages 300 col name for a20 select name,dest_ ...

  5. 为什么golang的开发效率高(编译型的强类型语言、工程角度高、在开发上的高效率主要来自于后发优势,编译快、避免趁编译时间找产品妹妹搭讪,既是强类型语言又有gc,只要通过编译,非业务毛病就很少了)

    作者:阿猫链接:https://www.zhihu.com/question/21098952/answer/21813840来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出 ...

  6. 2. Dubbo和Zookeeper的关系

    转自:https://www.cnblogs.com/hirampeng/p/9540243.html Dubbo建议使用Zookeeper作为服务的注册中心. 1.   Zookeeper的作用: ...

  7. vue-cli打包项目后,可以修改配置文件

    问题: 前端需要修改后台服务器地址url,写好的配置文件会在npm run build 后压缩在一起,传到运行的前端服务器上后,需要到前端打包的源码,找到url地址进行修改.如果不在打包的源码修改,则 ...

  8. 水题ing

    T1: https://www.luogu.org/problemnew/show/P1724幻想乡,东风谷早苗是以高达控闻名的高中生宅巫女.某一天,早苗终于入手了最新款的钢达姆模型.作为最新的钢达姆 ...

  9. 谈谈vector容器的三种遍历方法

    说明:本文仅供学习交流.转载请标明出处.欢迎转载!          vector容器是最简单的顺序容器,其用法相似于数组.实际上vector的底层实现就是採用动态数组.在编敲代码的过程中.经常会变量 ...

  10. 百度2019校招Web前端工程师笔试卷(9月14日)

    8月27日晚,在实习公司加班.当时正在调试页面,偶然打开百度首页console,发现彩蛋,于是投了简历. 9月14日晚,七点-九点,在公司笔试. 笔试题型(有出入): 一.单选20道 1.难度不难,考 ...