界面的表格导出为excel,并下载

最近,公司做了一个界面上的表格导出为excel并下载的一个功能.下面将具体的做法记录一下,以便后面复习.

首先先说一下需求

一.界面上有一个表格:

界面的表格导出为excel,并下载_第1张图片

就上面这个表格,我是写死的,要在界面上方有一个按钮,导出并下载的功能,上图中我还没有整理,见谅.

二.先做导出,我用的是poi导出,具体的例子网上有很多,需要导包什么的,这些我就不做多的介绍了

1.我先在 界面上写一个点击事件,使用window.open()方法进入到controller

$("#exportEx2").click(function () {
            var url = "${ctx}/analysis/mobileApp/" + _mobileAppId + "/demoExport2";
            alert("url:"+url);
            window.open(url, "_self");
        });

url是controller的地址,直接用window.open(),打开

2.后台controller的写法

@RequestMapping("/mobileApp/{mobileAppId}/demoExport2")
	@ResponseBody
	public void doExport2(@PathVariable("mobileAppId") int mobileAppId, String _mobileAppVersionId,HttpServletRequest request, HttpServletResponse response) throws IOException {
		// 文件名
		String filename = "自定义事件.xls";

		BufferedInputStream in = null;
		BufferedOutputStream out = null;
		try {
			List> list = new ArrayList>();
			for (int i = 0 ; i<18 ; i++) {
				//组装测试数据
				Map map = new HashMap();
				map.put("ri", ""+i);
				map.put("name", "test0"+i);
				map.put("age", "23");
				list.add(map);
			}

			// 第一步:定义一个新的工作簿
			XSSFWorkbook wb = new XSSFWorkbook();
			// 第二步:创建一个Sheet页
			XSSFSheet sheet = wb.createSheet("startTimeendTime");
			sheet.setDefaultRowHeight((short) (2 * 256));//设置行高
			sheet.setColumnWidth(0, 4000);//设置列宽
			sheet.setColumnWidth(1,5500);
			sheet.setColumnWidth(2,5500);
			XSSFFont font = wb.createFont();
			font.setFontName("宋体");
			font.setFontHeightInPoints((short) 16);

			XSSFRow row = sheet.createRow(0);
			XSSFCell cell = row.createCell(0);
			cell.setCellValue("流水号 ");
			cell = row.createCell(1);
			cell.setCellValue("姓名");
			cell = row.createCell(2);
			cell.setCellValue("年龄");

			XSSFRow rows;
			XSSFCell cells;
			for (int i = 0; i < list.size(); i++) {
				// 第三步:在这个sheet页里创建一行
				rows = sheet.createRow(i+1);
				// 第四步:在该行创建一个单元格
				cells = rows.createCell(0);
				// 第五步:在该单元格里设置值
				cells.setCellValue(list.get(i).get("ri"));

				cells = rows.createCell(1);
				cells.setCellValue(list.get(i).get("name"));
				cells = rows.createCell(2);
				cells.setCellValue(list.get(i).get("age"));
				cells = rows.createCell(3);
			}
			//开始执行写入操作
			String rootpath = request.getSession().getServletContext().getRealPath( "/");
			File file = new File(rootpath+"temp.xls");
			wb.write(new FileOutputStream(file));

			response.setContentType("application/vnd.ms-excel; charset=utf-8") ;
			String showName = "多事件/多维度表格.xlsx";
			response.setHeader("Content-Disposition", "attachment;filename=" + new String(showName.getBytes("UTF-8"), "iso8859-1"));
			in = new BufferedInputStream(new FileInputStream(file));
			out = new BufferedOutputStream(response.getOutputStream());
			byte[] data = new byte[1024];
			int len = 0;
			while (-1 != (len=in.read(data, 0, data.length))) {
				out.write(data, 0, len);
			}
		} catch (Exception e) {
			logger.error("download file encount error!");
		} finally {
			try {
				if (in != null) {
					in.close();
				}
				if (out != null) {
					out.close();
				}
			} catch (IOException e) {
				logger.error("download file colse io encount error!");
			}
		}
	}

首先这个controller的前面,我拼了一个List> ,这个里面存放的是数据.

后来使用了poi的一些api,去创建excel工作sheet等,这些我也就不细说了,回头好好看看poi的demo就啥都明白了,并且我这里是写死的数据,for循环都是遍历的死数据,还是比较简单,按理说写到这里,controller走完 ,前台就可以弹出一个框,也就是下面这个框:

界面的表格导出为excel,并下载_第2张图片

然后选择下载地址就可以导出并下载了,但是事情没有想象的那么简单,我点完按钮之后,发现跳转到了一个空白页面

window.open()函数原本就是打开一个页面,我设置的"_self",也就是在本浏览器页面再打开一个页面,但是没有打开,是为什么呢,后来一遍一遍试,并且叫来了老大帮我看,发现使我们的项目会拦截这个请求,也就是说我新写的一个controller没有再拦截器的配置页面配置,所以会拦截,接下来,我在拦截器的配置页面中配置了这个controller,就弹出来了,下来下来的excel的内容是我拼接的list中的内容.

3.接下来,我怎么获取到页面中的表格中的数据,然后传到后台呢,这就用到了jquery的知识,

首先我前段页面的表格其实就是一个table 如下:

时间 域名 城市 用户量 页面浏览量
09-12 周三 com.app.tingyun 北京 32 76
09-12 周四 com.app.tingyun 上海 32 76
09-12 周三 com.app.tingyun 广州 32 76

我可以试用jqyery遍历这个table,将其中的内容转换成json字符串,然后传到后台

遍历table的代码如下:

function getExcelJson(){
            var excelJson = new Array();
            $("#excelTable tr").each(function(i){
                var arr = new Array();
                $(this).children("td").each(function(j){
                    var aa = $(this).text();
                    arr.push($(this).text())
                });
                excelJson.push(arr);
            });
            var excelJsonTxt = JSON.stringify(excelJson);
            return excelJsonTxt;
        }

返回一个json类型的字符串,然后再url后面加上参数,使用get请求的方式传过去,其实这里肯定不能用get请求方式将这个参数传过去,得需要post请求,但是时间来不及了,我就先使用get方式传过去了,也没报错,后面我再修改成post请求方式吧,所以点击事件中的url修改为如下:

$("#exportEx2").click(function () {
            var excelJsonTxt = getExcelJson();
            var url = "${ctx}/analysis/mobileApp/" + _mobileAppId + "/demoExport2?excelJsonTxt="+encodeURIComponent(excelJsonTxt);
            alert("url:"+url);
            window.open(url, "_self");
        });

这里就是将excelJsonTxt 参数传过去,并且做了一下 encode处理,我这里就不多说了,搞过前端的都懂.

4.后面的controller 相应的也需要修改,接收到excelJsonTxt  参数后,动态的填充excel,controller如下:

/**
	 * @Description: 导出excel
	 * @auther:
	 * @date: 2018/9/30/0030 14:34
	 * @return
	 */
	@RequestMapping("/mobileApp/{mobileAppId}/demoExport2")
	@ResponseBody
	public void doExport2(@PathVariable("mobileAppId") int mobileAppId, String _mobileAppVersionId,HttpServletRequest request, HttpServletResponse response) throws IOException {
		// 文件名
		String filename = "自定义事件.xls";
		String excelJsonTxt = request.getParameter("excelJsonTxt");
		JSONArray jsonArray = JSON.parseArray(excelJsonTxt);

		BufferedInputStream in = null;
		BufferedOutputStream out = null;
		try {
			// 第一步:定义一个新的工作簿
			XSSFWorkbook wb = new XSSFWorkbook();
			// 第二步:创建一个Sheet页
			XSSFSheet sheet = wb.createSheet("startTimeendTime");
			sheet.setDefaultRowHeight((short) (2 * 256));//设置行高
			sheet.setColumnWidth(0, 4000);//设置列宽
			sheet.setColumnWidth(1,5500);
			sheet.setColumnWidth(2,5500);
			XSSFFont font = wb.createFont();
			font.setFontName("宋体");
			font.setFontHeightInPoints((short) 16);

			XSSFRow row = sheet.createRow(0);
			XSSFCell cell = row.createCell(0);
			JSONArray tHead = (JSONArray) jsonArray.get(0);
			for(int i=0; i

将接受到的excelJsonTxt 参数转换成JSONARRAY对象,然后填充到单元格中,后面的代码一看便知.

至此,导出为excel并下载将告一段落,其实其中还有很多没有明白的地方,以后在慢慢补充.

 

不积跬步,无以至千里

不积小流,无以成江海

你可能感兴趣的:(java学习)