将列表数据导出为Excel文件

  基本上任何系统都需要导出功能, 例如导出公司的财务报表、 导出公司的全部员工信息等。


  在此实现一个具有过滤指定字段的导出方法, 并对多表连接返回的复杂数据结构进行处理。


  前端代码(每个系统前端采用框架可能略有差别, 但是本质是一样的, 以下用jQuery EasyUI为例):主要功能就是获取前端表头数据, 然后把数据格式转换成适当格式发送到服务器端。

/**
 * @param dataGridId  导出数据的表格ID
 * @param exportUrl 导出数据请求的URL
 * @param excelTitle excel文件名
 * @param checkFlag 导出数据的表格是否有复选框(有复选框后台自动去掉该列)  0--无  1--有
 * @param reduceColnumName 不用导出的列名
 */
function exportExcelBaseInfo(dataGridId,exportUrl,excelTitle,checkFlag,reduceColnumName){
	var $dg = $("#"+dataGridId+"");
	
	var params=$dg.datagrid('options').queryParams; // 参数
	var columns=$dg.datagrid('options').columns; // 表头
	var v_pageNumber = $dg.datagrid('options').pageNumber;//当前页号
	var v_pageSize = $dg.datagrid('options').pageSize;//每页多少行记录
	
	// [Object, Object, ...] Object里面多余属性去除,就留下有用的字段, 节省带宽
	var columnsNew = [];
	$.each(columns,function(index,item){
		var dataArray = [];
		$.each(item,function(rowIndex,rowData){
			var v_object = {};
			v_object.field = rowData.field;
			v_object.title = rowData.title;
			dataArray[rowIndex] = v_object;
		});
		columnsNew[index] = dataArray;
	});
	
	// 对象的类型转换成Json类型
	//[Object, Object, ...] -----> "[[{"field":"name","title":"名称"},{"field":"gender","title":"性别"}, ... ]]"
	var exportColumns=JSON.stringify(columnsNew);
	
	var url=BasePath+exportUrl;
	
	// 行数据
	var dataRow=$dg.datagrid('getRows');

	$("#exportExcelForm").remove();
	
	// 使用form表单提交前端表头及参数
	$("<form id='exportExcelForm'  method='post'></form>").appendTo("body");
	
	var fromObj=$('#exportExcelForm');
	
	if(dataRow.length>0){
	    fromObj.form('submit', {
			url: url,
			onSubmit: function(param){
				param.exportColumns=exportColumns;
				param.fileName=excelTitle;
				param.checkFlag=checkFlag;
				param.reduceColnumName=reduceColnumName;
				param.pageNumber = v_pageNumber;
				param.pageSize = v_pageSize;
				if(params!=null&¶ms!={}){
					$.each(params,function(i){
						param[i]=params[i];
					});
				}
			},
			success: function(){
				
		    }
	   });
	}else{
		alert('记录为空,不能导出!',1);
	}
	

}


导出核心类: 放在MVC架构的C层, 以下代码以SpringMVC为例放在Controller层。因为每种系统业务不同, 在此不提供Service层和DAO层等代码。

    // 导出
	@RequestMapping(value = "/do_export",method=RequestMethod.POST)
	public void doExportMemberlist(HttpServletRequest req, Model model,
			HttpServletResponse response) throws ManagerException {
		Map<String, Object> params = new HashMap<String, Object>();
		String exportColumns = req.getParameter("exportColumns");
		String fileName = req.getParameter("fileName");
		String checkFlag = req.getParameter("checkFlag");
		//增加参数,该参数可以不指定,使用默认值
		String rowAccessWindowSizeStr = req.getParameter("rowAccessWindowSize");
		params.put("exportColumns", "exportColumns");
		params.put("fileName", "fileName");
		params.put("checkFlag", "checkFlag");
		params.put("rowAccessWindowSizeStr", "rowAccessWindowSizeStr");
		String reduceColnumName = StringUtils.isEmpty(req.getParameter("reduceColnumName")) ? "" : req
				.getParameter("reduceColnumName");

		if (!StringUtils.isNotEmpty(checkFlag)) {
			checkFlag = "0";
		}

		ObjectMapper mapper = new ObjectMapper();

		// 前端数据格式[[{"field":"name","title":"名称"},{"field":"gender","title":"性别"}, ... ]]
		// 转换为标准JSON格式
		if (StringUtils.isNotEmpty(exportColumns)) {
			try {
				exportColumns = exportColumns.replace("[", "");
				exportColumns = exportColumns.replace("]", "");
				exportColumns = "[" + exportColumns + "]";

				//Excel表头处理
				List<Map> columnsList = mapper.readValue(exportColumns, new TypeReference<List<Map>>() {
				});
			
				if (columnsList != null && columnsList.size() > 0) {
					// 有复选框字段则删除
					if (StringUtils.isNotEmpty(checkFlag) && checkFlag.equals("1")) {
						columnsList.remove(0);
					}
					// 删除不在Excel输出的行
					if (StringUtils.isNotEmpty(reduceColnumName)) {
						for (int i = 0; i < columnsList.size(); i++) {
							if (columnsList.get(i) != null) {
								if (columnsList.get(i).get("field") != null
										&& 
										reduceColnumName.equals(columnsList.get(i).get("field"))) {
									columnsList.remove(i);
									break;
								}
							}
						}
					}
				}

				List<ModelType> list = new ArrayList<ModelType>();
				// 输出到Excel的总行数
				int total = this.serviceMethod.findAllTriggerCount(params);
				SimplePage page = new SimplePage(1, total, (int) total);
				// 所有要输出的数据
				list = this.serviceMethod.findAllTriggerList(page, "", "", params);
				List<Map> listArrayList = new ArrayList<Map>();
				if (list != null && list.size() > 0) {
					for (ModelType vo : list) {
						Map map = new HashMap();
						ExportUtil.object2MapWithoutNull(vo, map);
						// 在此可以对数据库内容进行转换成实际值
						//   int sex = (Integer)map.get("gender");
						//   if (sex == 0) {
						//		map.put("sex", "男");
						//	 }else{
						//		map.put("sex", "女");
						//	 }
						listArrayList.add(map);

					}

					Integer rowAccessWindowSize = 1;
					if (rowAccessWindowSizeStr != null)
						rowAccessWindowSize = Integer.valueOf(rowAccessWindowSizeStr);
					
					HSSFExport.commonExportData(StringUtils.isNotEmpty(fileName) ? 
					                     fileName : "导出信息", columnsList,
							             listArrayList, response, rowAccessWindowSize);
				}
			} catch (Exception e) {
				// 异常处理
			}
		}
	}


工具类:

ExportUtil.java

public class ExportUtil {    
	// 将Object内容存入Map
	public static void object2MapWithoutNull(Object obj, Map<String,Object> map)
    		throws IllegalArgumentException, IllegalAccessException {
			
    	    // 获得类的所有申明的字段,即包括public、private和proteced,但是不包括父类的字段
			// 而getFields()获得某个类的所有的公共(public)的字段,包括父类
    		Field[] fields = obj.getClass().getDeclaredFields();
    		for (int j = 0; j < fields.length; j++) {
    		    fields[j].setAccessible(true);
				// 获取该属性值
	    		if(fields[j].get(obj) != null){
				    // 进行数据处理, 处理后放入Map中
	    			if((fields[j].get(obj) instanceof Date)){
	    				SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT);
	    				map.put(fields[j].getName(), sdf.format(fields[j].get(obj)));
	    			                                        // 复杂类型如List<Object>递归转换
	    				                                    // instanceof Object
	    			}else if((fields[j].get(obj) instanceof ModelType)){
	    				object2MapWithoutNull(fields[j].get(obj),map);
	    			}else{
	    				map.put(fields[j].getName(), fields[j].get(obj));
	    			}
	    		}else {
	    			map.put(fields[j].getName(),"");
				}
    		}
    	    // 父类数据转换
    		Field[] fields2 = obj.getClass().getSuperclass().getDeclaredFields();
    		for (int j = 0; j < fields2.length; j++) {
    			fields2[j].setAccessible(true);
	    		
	    		if(fields2[j].get(obj) != null){
	    			if((fields2[j].get(obj) instanceof Date)){
	    				SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT);
	    				map.put(fields2[j].getName(), sdf.format(fields2[j].get(obj)));
	    			}else{
	    				map.put(fields2[j].getName(), fields2[j].get(obj));
	    			}
	    		}else {
	    			map.put(fields2[j].getName(),"");
				}
    		}
    		
   }
}



生成Excel表类:HSSFExport.java

import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;
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.HSSFFooter;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.Footer;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;

/**
 * 导出查询数据到Excel表中(HSSF的开源框架)
 */
public final class HSSFExport {
	
	private HSSFExport() {
	
	}

	/**
	 * 导出数据到Excel, 获取jQuery EasyUI的表头信息与查询条件, 暂时不支持合并的表头, 纵横转换的表头是单独写的
	 * @param fileName         文件名
	 * @param ColumnsMapList   表头数据
	 * @param dataMapList      正文数据
	 * @param response  
	 * @param rowAccessWindowSize 导出excel过程中,如果需要访问导的第几行数据,则,需要给定这个参数为访问的excel行数;如传递的为空,则默认值为1行,
	 * 推荐使用默认值。 例如:如果想在程序中取得最后100行的数据,那么该参数=100; 否则就按照默认值导出。
	 * @throws Exception
	 */
	 
	public static void commonExportData(String fileName, List<Map> ColumnsMapList, List<Map> dataMapList,
			HttpServletResponse response, Integer rowAccessWindowSize) throws Exception {

		response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");

		String fileName2 = new String(fileName.getBytes("gb2312"), "iso-8859-1");
		//文件名
		response.setHeader("Content-Disposition", "attachment;filename=" + fileName2 + ".xlsx");
		response.setHeader("Pragma", "no-cache");

		if (rowAccessWindowSize == null) {

			rowAccessWindowSize = 1;
		}
        // 创建工作簿
		SXSSFWorkbook wb = new SXSSFWorkbook(rowAccessWindowSize.intValue());
		
		// 创建工作表
		Sheet sheet1 = wb.createSheet();
		wb.setSheetName(0, fileName);
		sheet1.setDefaultRowHeightInPoints(20);
		sheet1.setDefaultColumnWidth((short) 18);
		
		//设置页脚
		Footer footer = sheet1.getFooter();
		footer.setRight("Page " + HSSFFooter.page() + " of " + HSSFFooter.numPages());

		//设置样式 表头--第一行
		CellStyle style1 = wb.createCellStyle();
		style1.setAlignment(HSSFCellStyle.ALIGN_CENTER);
		Font font1 = wb.createFont();
		font1.setFontHeightInPoints((short) 13);
		font1.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
		style1.setFont(font1);
		
		//设置样式 表头--第二行
		CellStyle style2 = wb.createCellStyle();
		style2.setAlignment(HSSFCellStyle.ALIGN_LEFT);
		style2.setWrapText(true);
		
		//合并
		CellRangeAddress rg1 = new CellRangeAddress(0, (short) 0, 0, (short) (ColumnsMapList.size() - 1));
		sheet1.addMergedRegion(rg1);
		
		//设置样式 表头--第三行
		CellStyle style3 = wb.createCellStyle();
		style3.setAlignment(HSSFCellStyle.ALIGN_LEFT);
		Font font3 = wb.createFont();
		font3.setFontHeightInPoints((short) 18);
		font3.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
		style3.setFont(font3);
		style3.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
		style3.setFillPattern(CellStyle.SOLID_FOREGROUND);
		Row row0 = sheet1.createRow(0);
		row0.setHeightInPoints(35);
		
		//第一行 标题
		Cell cell0 = row0.createCell((short) 0);
		cell0.setCellValue(fileName.toString());
		cell0.setCellStyle(style3);

		//第二行 表头数据
		Row row1 = sheet1.createRow(1);
		row1.setHeightInPoints(20);
		for (int i = 0; i < ColumnsMapList.size(); i++) {
			Cell cell1 = row1.createCell(i);
			cell1.setCellType(HSSFCell.ENCODING_UTF_16);
			cell1.setCellValue(ColumnsMapList.get(i).get("title").toString());
			cell1.setCellStyle(style1);
		}

		//第三行 填充数据
		for (int j = 0; j < dataMapList.size(); j++) {
			Row row2 = sheet1.createRow((j + 2)); // 第三行开始填充数据 
			Map cellDataMap = dataMapList.get(j);
			for (int i = 0; i < ColumnsMapList.size(); i++) {
				Cell cell = row2.createCell(i);
				String cellValue = StringUtils.EMPTY;
				if (ColumnsMapList.get(i).get("field") != null) {
					String fieldString = String.valueOf(ColumnsMapList.get(i).get("field"));
					cellValue = String.valueOf(cellDataMap.get(fieldString));
				}
				cell.setCellValue(cellValue);
				cell.setCellStyle(style2);
			}

		}
        // 将以上缓存内容写到Excel中
		wb.write(response.getOutputStream());
		response.getOutputStream().flush();
		response.getOutputStream().close();
		wb.dispose();
	}
}



  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值