SpringMVC + Apache POI 实现WEB中Excel下载功能

简介: 项目中需要将web页面中的报表导出成Excel,在网上搜寻了写资料,实现了相关功能,如图1所示: 项目后台架构采用的是SpringMVC+Spring+Mybatis,通过引入Apache POI实现excel的下载功能。
项目中需要将web页面中的报表导出成Excel,在网上搜寻了写资料,实现了相关功能,如图1所示:


项目后台架构采用的是SpringMVC+Spring+Mybatis,通过引入Apache POI实现excel的下载功能。
导出效果如图2所示:

首先页面中点击“导出Excel”按钮就会触发如下js代码:
function getXls()
{
    var selectVal = dijit.byId('DRSSelectFacId').get('value');
    var beginTimeVal = dijit.byId('DRSBeginTime').get('displayedValue');
    var endTimeVal = dijit.byId('DRSEndTime').get('displayedValue');  
    
    var url = "report/getDRSExcel.do?"+"fac_id="+selectVal+"&beginTime="+beginTimeVal+"&endTime="+endTimeVal;
    window.open(url,"_self");
}
这段js代码的主要功能是将选择条件返回给后台,请求相应的数据并生成excel。
jsp相关代码如下:
                    	<div style="margin-top:10px;">
	                    	<label for="DRSSelectFacId">选择电场:</label><span id="DRSSelectFacId" ></span>    
	                    	<label for="DRSBeginTime">起始日期:</label><span id="DRSBeginTime" ></span>    
	                    	<label for="DRSEndTime">截止日期:</label><span id="DRSEndTime" ></span>    
                            <span id="DRSbutton1" ></span>    
                            <span id="DRSbutton2" ></span>
                    	</div>


下面是JAVA后台控制层代码:
	@RequestMapping(value = "/report/getDRSExcel.do")
	public void getDRSExcel(
			@RequestParam(value = "fac_id", required = true) String fac_id,
			@RequestParam(value = "beginTime", required = true) String beginTime,
			@RequestParam(value = "endTime", required = true) String endTime,
			HttpServletRequest request, HttpServletResponse response)
	{
		logger.info("/report/getDRSExcel.do?fac_id=" + fac_id + "&beginTime="
				+ beginTime + "&endTime=" + endTime);
        try {
			this.daliyRepShortService.getXls(fac_id,beginTime,endTime,request,response);
		} catch (ParseException e) {
			e.printStackTrace();
		}
    }
这里调用了业务层代码如下:
    private List<Map<String, Object>> createExcelRecord(List<Fc_dailyreport> projects) {
        List<Map<String, Object>> listmap = new ArrayList<Map<String, Object>>();
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("sheetName", "短期预测日报");
        listmap.add(map);
        Fc_dailyreport project=null;
        
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        DecimalFormat fnum = new DecimalFormat("##0.0000"); 
        for (int j = 0; j < projects.size(); j++) {
            project=projects.get(j);
            Map<String, Object> mapValue = new HashMap<String, Object>();
            mapValue.put("dtime", sdf.format(project.getDtime()));
            mapValue.put("cap", project.getCap());
            mapValue.put("p", project.getP());
            mapValue.put("fore_p", project.getFore_p());
            mapValue.put("rmse", fnum.format(project.getRmse()*100)+"%");
            mapValue.put("mae", fnum.format(project.getMae()*100)+"%");
            mapValue.put("qualified_rate", project.getQualified_rate()+"%");
            mapValue.put("colrel", project.getColrel());
            mapValue.put("uploadrate", project.getUploadrate()+"%");
            mapValue.put("qxuploadrate", project.getQxuploadrate()+"%");
            listmap.add(mapValue);
        }
        return listmap;
    }
    
    public void getXls(String fac_id,String beginTime,String endTime,HttpServletRequest request, HttpServletResponse response) 
    		throws ParseException
    {
    	String fileName="短期预测日报";
    	//1. 
    	List<Fc_dailyreport> projects = getXlsData(fac_id,beginTime,endTime);
    	//2.
    	List<Map<String,Object>> list=createExcelRecord(projects);
    	//3.
    	String columnNames[]={"时间","容量(MW)","实际功率(MW)","预测功率(MW)","均方误差(%)","平均绝对误差(%)","合格率(%)","相关系数","上传率(%)","气象上传率(%)"};//列名
        String keys[]   =    {"dtime","cap","p","fore_p","rmse","mae","qualified_rate","colrel","uploadrate","qxuploadrate"};//map中的key
        //4.
        ExcelUtil.ExcelSingleOutputStream(list,keys,columnNames,fileName,request,response);
    }
在getXls方法中, getXlsData(fac_id,beginTime,endTime);主要是根据前端的查询条件参数获取所要的数据,这里采用的是mybatis实现,由于本文的主旨是与excel相关的,这里就不说明mybatis如何实现数据的获取。
第二步是创建excel的数据,如方法 createExcelRecord(projects);所示。list中第一项的 sheetName用来命名Excel中的sheet。剩余list中的数据数excel中的没一行的数据。在getXls方法中的columnNames对应excel的第一行的列名,可参考图2. keys与createExcelRecord中的相关名字一一对应(这里也与DAO值的pojo类的属性名字一一对应)。
接下来就需要了解 ExcelUtil.ExcelSingleOutputStream(list,keys,columnNames,fileName,request,response);这一段代码是做什么的了。
首选看类ExcelUtil:
package com.shr.util;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.poi.hssf.usermodel.HSSFWorkbook;
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.IndexedColors;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;

public class ExcelUtil {

    public static Workbook createSingleWorkBook(List<Map<String, Object>> list,String []keys,String columnNames[]) {
        Workbook wb = new HSSFWorkbook();
        Sheet sheet = wb.createSheet(list.get(0).get("sheetName").toString());
        for(int i=0;i<keys.length;i++)
        {
            sheet.setColumnWidth((short) i, (short) (35.7 * 150));
        }

        Row row = sheet.createRow((short) 0);

        CellStyle cs = wb.createCellStyle();
        CellStyle cs2 = wb.createCellStyle();

        Font f = wb.createFont();
        Font 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.setFillForegroundColor(IndexedColors.AQUA.getIndex());
        cs.setFillPattern(CellStyle.SOLID_FOREGROUND);
        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);
        for(int i=0;i<columnNames.length;i++){
            Cell cell = row.createCell(i);
            cell.setCellValue(columnNames[i]);
            cell.setCellStyle(cs);
        }
        for (short i = 1; i < list.size(); i++) {
            Row row1 = sheet.createRow((short) i);
            for(short j=0;j<keys.length;j++){
                Cell cell = row1.createCell(j);
                cell.setCellValue(list.get(i).get(keys[j]) == null?" ": list.get(i).get(keys[j]).toString());
                cell.setCellStyle(cs2);
            }
        }
        return wb;
    }
    
    public static void ExcelSingleOutputStream(List<Map<String, Object>> list,String []keys,String columnNames[],
    		String fileName, HttpServletRequest request, HttpServletResponse response)
	{
    	ByteArrayOutputStream os = new ByteArrayOutputStream();
    	try {
 			createSingleWorkBook(list,keys,columnNames).write(os);
		} catch (IOException e2) {
			e2.printStackTrace();
		}
    	ExcelOutputStream(fileName,request,response,os);
	}
    
    private static void ExcelOutputStream( String fileName, HttpServletRequest request, HttpServletResponse response,ByteArrayOutputStream os)
    {
        byte[] content = os.toByteArray();
        InputStream is = new ByteArrayInputStream(content);
        
        response.reset();
        response.setContentType("application/vnd.ms-excel;charset=utf-8");
        try {
			response.setHeader("Content-Disposition", "attachment;filename="+ new String((fileName + ".xls").getBytes(), "iso-8859-1"));
		} catch (UnsupportedEncodingException e1) {
			e1.printStackTrace();
		}
        ServletOutputStream out = null;
		try {
			out = response.getOutputStream();
		} catch (IOException e1) {
			e1.printStackTrace();
		}
        BufferedInputStream bis = null;
        BufferedOutputStream bos = null;

        try {
            bis = new BufferedInputStream(is);
            bos = new BufferedOutputStream(out);
            byte[] buff = new byte[2048];
            int bytesRead;
            while (-1 != (bytesRead = bis.read(buff, 0, buff.length))) {
                bos.write(buff, 0, bytesRead);
            }
        } catch ( IOException e) {
            e.printStackTrace();
        } finally {
            if (bis != null)
				try {
					bis.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
            if (bos != null)
				try {
					bos.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
        }
    }
}

这里的createSingleWorkBook方法用来根据业务层中的相关数据生成的excel,这时候生成的excel是驻留在内存中的,所以需要其输出,请参照方法ExcelSingleOutputStream和ExcelOutputStream(这里将一个方法拆分成两个是因为原项目中还有其他的情况考虑,本文只罗列出一种相对简单的情况,所以这样不要差异,可以将这两个方法看成一个也无妨,主要是向页面输出这个生成的Excel。









目录
相关文章
|
前端开发 安全 Java
技术进阶:使用Spring MVC构建适应未来的响应式Web应用
【9月更文挑战第2天】随着移动设备的普及,响应式设计至关重要。Spring MVC作为强大的Java Web框架,助力开发者创建适应多屏的应用。本文推荐使用Thymeleaf整合视图,通过简洁的HTML代码提高前端灵活性;采用`@ResponseBody`与`Callable`实现异步处理,优化应用响应速度;运用`@ControllerAdvice`统一异常管理,保持代码整洁;借助Jackson简化JSON处理;利用Spring Security增强安全性;并强调测试的重要性。遵循这些实践,将大幅提升开发效率和应用质量。
317 7
|
缓存 前端开发 Java
打造未来兼容的Web应用:Apache Wicket引领响应式设计的热潮
【9月更文挑战第4天】在软件开发领域,构建响应式Web应用至关重要。Apache Wicket作为一个强大的Java框架,支持响应式设计,确保应用在不同设备上均有出色体验。本文通过示例代码介绍使用Wicket的最佳实践,涵盖页面与组件模型、CSS媒体查询及自定义标记处理器的应用。同时,文章强调了优化加载时间、增强交互性和提升可访问性的重要性,帮助开发者打造高性能且美观的Web应用。
327 3
|
Java API Apache
从零到英雄的蜕变:如何用Apache Wicket打造你的第一个Web应用——不仅是教程,更是编程之旅的启航
【9月更文挑战第4天】学习Apache Wicket这一开源Java Web应用框架是一段激动人心的旅程。本文将指导你通过Maven搭建环境,并创建首个“Hello, World!”应用。从配置`pom.xml`到实现`HelloWorldApplication`类,再到`web.xml`的设置,一步步教你构建与部署简单网页。适合初学者快速上手,体验其简洁API与强大组件化设计的魅力。
636 1
|
开发者 前端开发 Apache
Apache Wicket Ajax揭秘:轻松几步,让你的Web应用告别“呆板”,焕发新生!
【8月更文挑战第31天】随着互联网技术的发展,Web应用的交互性成为评价网站成功的关键指标。Apache Wicket作为一款卓越的Java Web框架,不仅具备强大的组件化开发能力,还内置了对Ajax技术的支持,使开发者能轻松提升Web应用的交互体验。通过简单的代码示例展示了如何在不刷新页面的情况下异步更新页面元素,极大提升了用户体验。Wicket提供了多种Ajax组件和行为,如AjaxFallbackLink、AjaxButton等,满足不同场景需求,并支持自定义Ajax行为,帮助开发者实现复杂交互效果。合理运用Wicket的Ajax功能,可显著增强网站竞争力。
441 1
|
Ubuntu 应用服务中间件 Linux
在Linux中,如何配置Web服务器(如Apache或Nginx)?
在Linux中,如何配置Web服务器(如Apache或Nginx)?
|
前端开发 JavaScript Java
导出excel的两个方式:前端vue+XLSX 导出excel,vue+后端POI 导出excel,并进行分析、比较
这篇文章介绍了使用前端Vue框架结合XLSX库和后端结合Apache POI库导出Excel文件的两种方法,并对比分析了它们的优缺点。
3170 0
|
Java Apache
Apache POI java对excel表格进行操作(读、写) 有代码!!!
文章提供了使用Apache POI库在Java中创建和读取Excel文件的详细代码示例,包括写入数据到Excel和从Excel读取数据的方法。
2334 0
|
Java 开发者 前端开发
Struts 2、Spring MVC、Play Framework 上演巅峰之战,Web 开发的未来何去何从?
【8月更文挑战第31天】在Web应用开发中,Struts 2框架因强大功能和灵活配置备受青睐,但开发者常遇配置错误、类型转换失败、标签属性设置不当及异常处理等问题。本文通过实例解析常见难题与解决方案,如配置文件中遗漏`result`元素致页面跳转失败、日期格式不匹配需自定义转换器、`&lt;s:checkbox&gt;`标签缺少`label`属性致显示不全及Action中未捕获异常影响用户体验等,助您有效应对挑战。
383 0
|
Java Spring Apache
Spring Boot邂逅Apache Wicket:一次意想不到的完美邂逅,竟让Web开发变得如此简单?
【8月更文挑战第31天】Apache Wicket与Spring Boot的集成提供了近乎无缝的开发体验。Wicket以其简洁的API和强大的组件化设计著称,而Spring Boot则以开箱即用的便捷性赢得开发者青睐。本文将指导你如何在Spring Boot项目中引入Wicket,通过简单的步骤完成集成配置。首先,创建一个新的Spring Boot项目并在`pom.xml`中添加Wicket相关依赖。
635 0
|
Apache 开发者 Java
Apache Wicket揭秘:如何巧妙利用模型与表单机制,实现Web应用高效开发?
【8月更文挑战第31天】本文深入探讨了Apache Wicket的模型与表单处理机制。Wicket作为一个组件化的Java Web框架,提供了多种模型实现,如CompoundPropertyModel等,充当组件与数据间的桥梁。文章通过示例介绍了模型创建及使用方法,并详细讲解了表单组件、提交处理及验证机制,帮助开发者更好地理解如何利用Wicket构建高效、易维护的Web应用程序。
503 0

推荐镜像

更多