poi导出excel,实现一个excel中多个sheet(可解决poi导出限制65536的问题)

本文章的excel实现导出多个sheet是在上一篇poi导出的基础上实现的,这么久了,对于上一篇文章的poi也作出过一些优化。

这里我只贴修改了的方法的代码,其余的和上一篇文章的一样。

/**
	 * 导出excel.在一个页面中单独导出Excel
	 * 
	 * @param titleColumn 对应bean的属性名
	 * @param titleName   excel要导出的表名
	 * @param titleSize   列宽
	 * @param dataList    数据
	 */
	public void wirteExcel(String titleColumn[], String titleName[], int titleSize[], List<?> dataList) {
		long startTime = System.currentTimeMillis();
		HttpServletRequest request = ServletActionContext.getRequest();
		// 新建文件
		OutputStream out = null;
		try {
			if (fileDir != null) {
				deleteExcel(fileDir);
				// 有文件路径
				out = new FileOutputStream(fileDir);
			} else {
				// 否则,直接写到输出流中
				out = response.getOutputStream();
				fileName = fileName + ".xls";
				log.info("导出excel,文件为:"+fileName);
				response.setContentType("application/x-msdownload");
				final String userAgent = request.getHeader("USER-AGENT"); // 获取浏览器的代理
				// 下面主要是让文件名适应不同浏览器的编码格式
				String finalFileName = null;
				if (StringUtils.contains(userAgent, "MSIE")) {
					finalFileName = URLEncoder.encode(fileName, "UTF8");
				} else if (StringUtils.contains(userAgent, "Mozilla")) {// google,火狐浏览器
					finalFileName = new String(fileName.getBytes(), "ISO8859-1");
				} else {
					finalFileName = URLEncoder.encode(fileName, "UTF8");// 其他浏览器
				}
				response.setHeader("Content-Disposition", "attachment; filename=\"" + finalFileName + "\"");
			}

			if(dataList!=null) {
				// 求总sheet数量,pageCount为每个sheet中数据的数量,此处我设置的是10000条
				int pageCount = 10000;
				final int sheetNum = (int) Math.ceil((float) dataList.size() / pageCount);
				log.info("excel中sheet数量:"+sheetNum);
				for (int n = 1; n <= sheetNum; n++) {
					// 添加Worksheet(不添加sheet时生成的xls文件打开时会报错)
					String sheetNames = this.sheetName + "_" + n;
					final HSSFSheet sheet = workbook.createSheet(sheetNames);
					
					// 写入excel的表头
					HSSFRow titleNameRow = sheet.createRow(0);
					
					// 设置样式
					HSSFCellStyle titleStyle = workbook.createCellStyle();
					titleStyle = (HSSFCellStyle) setFontAndBorder(titleStyle, titleFontType, (short) titleFontSize);
					titleStyle = (HSSFCellStyle) setColor(titleStyle, titleBackColor, (short) 10);
					titleStyle.setAlignment(XSSFCellStyle.ALIGN_CENTER);

					for (int i = 0; i < titleName.length; i++) {
						sheet.setColumnWidth(i, titleSize[i] * 256); // 设置宽度
						Cell cell = titleNameRow.createCell(i);
						cell.setCellStyle(titleStyle);
						cell.setCellValue(titleName[i].toString());
					}

					// 获取内容设置样式
					CellStyle doubleStyle = createCellContent4DoubleStyle(workbook);
					CellStyle integerStyle = createCellContent4IntegerStyle(workbook);
					CellStyle contentStyle = createCellContentStyle(workbook);
					titleStyle = (HSSFCellStyle) setFontAndBorder(titleStyle, contentFontType, (short) contentFontSize);
					// 通过反射获取数据并写入到excel中
                    // 先循环获取每个sheet中数据的下标,取出数据存入useList
					if (dataList != null && dataList.size() > 0) {
						if (titleColumn.length > 0) {
							int list_num_start = pageCount*(n-1); // 开始下标
							int list_num_end = (sheetNum == n?(n-1):n)*pageCount+(sheetNum == n?dataList.size()%pageCount:0); // 结束下标
							// 将本sheet数据加入到集合中
							List<Object> useList = new ArrayList<>();
							for (int j = list_num_start; j < list_num_end; j++) {
								Object object = dataList.get(j);
								useList.add(object);
							}
							
							HSSFRow rowTemp = null;
							HSSFCell celltemp = null;
							// 将集合数据写入到该sheet
							int y = 0; // 用于行,迭代器没有下标,所以要自己设置行数
							for (Iterator iterator = useList.iterator(); iterator.hasNext();) {
								Object obj = (Object) iterator.next();
								Class clsss = obj.getClass(); // 获得该对对象的class实例
								y = y+1; // 定义行
								rowTemp = sheet.createRow(y); // 将数据写入第y行中

								// 将数据写入对应列中
								int a = 0;
								for (int columnIndex = 0; columnIndex < titleColumn.length; columnIndex++) {
									String title = titleColumn[columnIndex].toString().trim();
									if (!"".equals(title)) { // 字段不为空
										// 使首字母大写
										String UTitle = Character.toUpperCase(title.charAt(0))
												+ title.substring(1, title.length()); // 使其首字母大写;
										String methodName = "get" + UTitle;
										// 设置要执行的方法
										Method method = clsss.getDeclaredMethod(methodName);

										// 获取返回类型
										Class<?> returnType2 = method.getReturnType();
										String returnType = returnType2.getName();
										String data = method.invoke(obj) == null ? "" : method.invoke(obj).toString();
										
										int x = a++; // 定义列
										celltemp = rowTemp.createCell(x); // 将数据写入行中
										if (data != null && !"".equals(data)) {
											if ("int".equals(returnType)) {
												celltemp.setCellValue(Integer.parseInt(data));
												celltemp.setCellStyle(integerStyle);
											} else if ("long".equals(returnType)) {
												celltemp.setCellValue(Long.parseLong(data));
												celltemp.setCellStyle(integerStyle);
											} else if ("float".equals(returnType)) {
												celltemp.setCellValue(Float.parseFloat(data));
												celltemp.setCellStyle(doubleStyle);
											} else if ("double".equals(returnType)) {
												celltemp.setCellValue(Double.parseDouble(data));
												celltemp.setCellStyle(doubleStyle);
											} else {
												if (data.matches("\\d+") == true) {// 判断能否转成数字
													celltemp.setCellValue("'" + data);// 转换成文本形式 避免 0001导出变成1
												} else {
													celltemp.setCellValue(data);
												}
											}
										}
									}
								}
							}
						}
					}
				}
			}
			log.info("导出excel");
			workbook.write(out);
			long endTime = System.currentTimeMillis();
			log.info("数据全部导出至excel总耗时:" + (endTime - startTime) + "ms;数据长度:" + dataList.size());
			// 当前JVM占用的内存总数(M)
			double total = (Runtime.getRuntime().totalMemory()) / (1024.0 * 1024);
			log.info("当前JVM占用的内存总数(M):"+ total);
			// JVM最大可用内存总数(M)
			double max = (Runtime.getRuntime().maxMemory()) / (1024.0 * 1024);  
			log.info("JVM最大可用内存总数(M):"+ max);
			// JVM空闲内存(M)
			double free = (Runtime.getRuntime().freeMemory()) / (1024.0 * 1024);  
			log.info("JVM空闲内存(M):"+ free);
			// 可用内存内存(M)
			double mayuse=(max - total + free);
			log.info("可用内存内存(M):"+ mayuse);
			// 已经使用内存(M)
    		double used=(total-free);
    		log.info("已经使用内存(M):"+ used);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				out.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

之前的代码中设置样式时,每次写入数据时,都去调用了设置样式的方式,poi创建样式的次数是有限制的,一旦超出限制便会报错。

那么就需要像现在写的代码一样,先调用样式方法,将样式先获取出来

然后写入excel时再给已经获取好的样式。

celltemp.setCellStyle(doubleStyle);

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值