1、页面添加导出按钮
<a class="nui-button" onclick="downloadExcel()">Excel</a>
2、在JavaScript中添加downloadExcel()事件:
function downloadExcel(){
var url ="<%= request.getContextPath%>"+"/xxxExcelCtrl/exportxxxExcel.do?";
var fields = form.getFields();//获取查询Form数组
var formItem;
for(var i=0,fieldsLen=fields.length;i<fieldsLen;i++){
formItem = fields[i].name;//单个name值
if(i==0){
url += formItem + "=" + $J.getbyName(formItem).getValve();
}else{
url += "&"+formItem + "=" + $J.getbyName(formItem).getValve();
}
}
window.location.href = url;
}
3、Ctrl请求层(TradeVO:接收页面传过来的参数对象)
@Controller
@RequestMapping("/xxxExcelCtrl")
public class ExcelExportCtrl extends BaseCtrl{
@FunctionDesc("导出功能")
@ResponseBody
public void exportxxxExcel(TradeVO vo , HttpServletResponse response){
iExcelExportService.exportxxxTrade(vo,response);
}
}
4、Service接口
public void exportxxxTrade(TradeVO vo,HttpServletResponse response);
5、Service方法的实现
@Service("iExcelExportService")
public class ExcelExportServiceImpl implements IExcelExportService{
//通过枚举类获取对象
private ExportExcelEnum exportExcel = ExportExcelEnum.INSTANCE;
private static final int END = 3000;
private static final int START = 0;
private static final String SPLIT = ",";
//分割map时使用
private static final String COLON = ":";
private static final String FILE_XLS = ".xls";
private IDirectoryService directoryService;
private static final String DEFAULT_CHARSET = "UTF-8";
private static final String HEADERS = "Headers";
private static final String FIELDS = "Fields";
private static final String CODES = "Codes";
private static final int ZERO = 0;//中文属性名所在行
private Map<String, String[]> headersMap = new HashMap<String, String[]>();
private Map<String, String[]> fieldsMap = new HashMap<String, String[]>();
private Logger logger = LoggerFactory.getLogger(ExcelExportServiceImpl.class);
// 第一个Map以excelID+Codes作为Key,value=(第二个Map以数据库中的值为Key(对象的属性字段),value为tradeState(码表编码)),如果没有则可去掉
private Map<String, Map<Integer, String>> codesMap = new HashMap<String, Map<Integer, String>>();
public void exportxxxTrade(TradeVO vo,HttpServletResponse){
List<TradeVO> result= iFiccxxxTradeDao.findxxxTradeList(vo,START,END)//从数据库中获取需要在Excel中显示的数据集合;
bulidExcel(ExcelConstants.TRADE_EXCELID,result,response);
}
public void buildExcel(String execelID, List<?> records, HttpServletResponse response){
String[] headerArr = null;
String[] fieldArr = null;
String[] codeArr = null;
Map<Integer,String> codeMap = null;
String headerKey = execelID + HEADERS;
String fieldsKey = excelID + FIELDS;
String codesKey = excelID + CODES;
//获取Excel中头信息显示列表,从配置文件exportExcel.properties中获取
if(headersMap.get(headerKey) == null){
try{
String headerValue = new String(exportExcel.getValue(headerKey).getBytes("ISO-8859-1"),DEFAULT_CHARSET );
headArr = headerValue.split(SPLIT);
headersMap.put(headerValue,headArr);
}catch(){
logger.error("exprotExcel获取Headers出错",headerKey);
}
}else{
headerArr = headersMap.get(headerKey);
}
//获取Excel中从数据库中查询得到结果的返回字段(既返回对象的属性)
if(fieldsMap.get(fieldsKey == null)){
fieldArr = exportExcel.getValue(fieldsKey).split(SPLIT);
fieldsMap.put(fieldsKey,fieldArr);
} else {
fieldArr = fieldsMap.get(fieldsKey);
}
if(codesMap.get(codesKey) == null){
codeArr = exportExcel.getValue(codesKey).split(SPLIT);
String codeMapping = null;// 位置索引:码表编码
codeMap = new hashMap<Integer, String>();
for(int i=0; i<codeArr.length; i++){
codeMapping = codeArr[i].split(COLON);
codeMap.put(codeMapping[0],codeMapping[1]);
}
codesMap.put(codeKey,codeMap);//放入缓存
}else{
codeMap = codesMap.get(codeKey);
}
//HSSFWorkbook为excel表的导出和设置(需要更多需求可以查看API)
HSSFWorkbook() workbook = new HSSFWorkbook();//创建一个和Excel文件
HSSFSheet sheet = workbook.createSheet();//创建一个Excel的sheet
sheet.setDefaultColumnWidth(17);设置列宽
//设置sheet头样式
HSSFCellStyle headerStyle = workbook.createCellStyle();
headerStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);//左右居中
//设置字体
HSSFFont headerFont = workbook.createFont();
headerFont.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);//加粗
headerFont.setFontHeightInPoints((short) 12);//字体大小
//将字体样式设置到头样式中
headerStyle.setFont(headerFont);
//设置单元格样式
HSSFCellStyle cellStyle = workbook.createCellStyle();
cellStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);
//创建文件头(既第一行)
buildHeaders(sheet,headerArr,headerStyle);
//遍历从数据库中获取到的信息
buildFields(sheet, fieldArr, recores, cellStyle, codeMap);
wroteFile(workbook, excelID ,response);
}
//将文件写入Response中
private void writeFile(HSSFWorkbook workbook,String excelID, HttpServletResponse response){
ServletOutputStream out = null;//此类提供了将二进制数据写入响应的流
try{
response.setContentType("application/vnd.ms-excel;charset=utf-8");
//HTTP下载请求头:Content-Disposition: attachment; filename=FileName.txt
//Content-Disposition就是当用户想把请求所得的内容存为一个文件的时候提供一个默认的文件名
response.setHeader("Content-Disposition",new StringBuilder("attachment;filename=").append(execelID)
.append(FILE_XLS).toString());
out = response.getOutputStream();
workbook.write(out);
}catch(Exception e){
logger.error("输入文件流写出到response输出流失败:{}",e.toString());
throw new BusinessException("文件下载失败");
}finally{
try{
workbook.close();
out.close();
}catch(Exception e){
logger.error("输出文件流关闭失败:{}",e.toString());
throw new BusinessException("输出文件流关闭失败");
}
}
}
//写Excel文件头
private void buildHeaders(HSSFSheet sheet, String[] headerArr, HSSFCellStyle headerStyle){
HSSFRow headRow = sheet.createRow();//创建Excel表头
headRow.setHeightInPoints(25);
HSSFCell firstCell = headRow.createCell(ZERO);//首行首列
firstCell.setCellStyle(headerStyle);
HSSFCell headCell = null;
for(int colum = 1,length = headerArr.length; colum < lenth; colum++){
headCell = headRow.createCell(colum);
headCell.setCellValue(headerArr[colum-1]);//头信息添加了“序号”所以需要-1;
headCell.setCellStyle(headerStyle);
}
}
//写Excel文件数据部分
private void buildFields(HSSFSheet sheet, String[] field fieldArr, List<?> records,
HSSFCellStyle cellStyle, Map<Integer, String> codeMap){
//可以将对象转换成json数据
ObjectMapper mapper = new ObjectMapper();
String objString = null;//当个对象的String
JsonNode node = null;//单个对象的JsonNode
String fieldValue = null;
JsonNode cellNode = null;
HSSFRow row = null;//数据行
HSSFCell cellSort = null;//序号列
HSSFCell fieldCell = null;//数据列
for(int i = 0 ,recordSize = recodes.size(); i < recordSize; i++){
try{
objString = mapper.writeValueAsString(records.get(i));
node = mapper.readTree(objString);
row = sheet.createRow(i+1);//从第二行开始
for(int j = 0 , fieldLen = fieldArr.length; j< fieldLen ; j++){
if(j == 0){//序号列赋值
cellSort = row.createCell(ZERO);
cellSort.setCellValue(i+1);
}
cellNode = node.path(fieldArr[j])//循环获取单个对象的所有属性值
if(cellNode.isNull()){
fieldValue = "";
}else{
if(fieldValue.isTextual()){
fieldValue= cellNode.asText();
}else if(fieldValue.isNumber()){
fieldVaule= cellNode.decimalValue().toPlainString();
}
//第j个属性需要从码表中获取中文
if(codeMap.get[j] != null){
fieldValue= getCodeValue(codeMap.get[j],fieldValue);
}
}
fieldCell = row.createCell(j+1);//第一列为序号
fieldCell.setCellValue(fieldValue);
fieldCell.setStyle(cellStyle);
}
}catch(Exception e){
logger.error("exportExcel从数据库中取得数据对象放入Excel失败:{}",e.toString());
}
}
}
/**获取码表
* @param typeCode : 码表的ID
* @infoCode : 码表中整数值
* @return roleName : 码表中整数对应的value值
*/
public String getCodeValue(String typeCode, String infoCode){
String roleName = null;
try{
if(directoryService == null){
directoryService = (IDirectoryService)ContextUtil.getBean("directoryService");
}
IPCodeInfoVO ipCodeInfoVO = directoryService.findInfoByTypeCodeAndInfoCode(typeCode, infoCode);
roleName = ipCodeInfoVO.getMbtmz();
}catch(Exception e){
logger.error("获取码表信息失败typeCode:{},infoCode:{}",typeCode,infoCode);
}
if(null == roleName || "".equals(roleName)){
return "";
}
return roleName;
}
}
6、Excel导出的实体类(用来存放service中的EXCELID)
public class ExceConstants{
public static final String TRADE_EXCELID = "xxxTradeExportList";//导出文件的ID,不同业务ExcelID不相同
}
7、exportExcel.properties配置文件
#xxx:表示上述定义的excelID,Headers表示导出的Excel表头(英文逗号分隔)
xxxHeaders=交易流水号,业务编号,交易状态,起息日,交易机构
#导出字段属性,以表头中中文保持一致,且与数据库返回的字段一致。
xxxxFields=blocknumber,businessNo,tradeStatus,tradeValue,bankIdName
#码表数值转义成中文格式,所在位置:码表编号ID
xxxCodes=2:tradeState