poi 导出Excel 含多个sheet、版本问题、保存问题小解

这两天做了一个poi导出多个sheet,以及向sheet里面插入图片的功能。
前提 我们是前后端分离模式(页面上所有功能实现、数据获取都由前端实现,java仅负责写接口以供调用)
接口思路是先生成一个文件 ,保存在服务器上,返回一个url给前端,前端可以直接访问。
说下遇到的问题:

  1. 版本兼容问题
    我的excel版本是最新版,下载之后打开并没有问题,我同事应该是2007的,他的打开文件就弹出数据丢失提示,但是数据其实是完整的,并没有丢失。

2.保存和下载的问题

第一个问题
提示数据丢失,是老的版本有一些表达式不支持,改一下引用的包就好了。
本来我用的是 HSSFWorkbook 这个类,后来遇到第一个问题之后,换成了XSSFWorkbook这个类,2007版本打开没问题,更高版本的也可以兼容。
另外 有一个插入图片的功能,XSSFDrawing(图画管理器)都要用配套的,设置图片属性的HSSFClientAnchor类换成ClientAnchor就OK了,参数和HSSFClientAnchor类一样。

第二个问题

get请求过去访问接口就直接下载下来了,post请求返回来的东西打印出来全都是乱码,并且在我本来用response返回输出json的那行报错了:
(java.lang.IllegalStateException: getOutputStream() has already been called for this response)
这个问题是因为同一条请求用response给了两次返回报出来的,后来仔细检查了代码,发现有个方法里面封装了这些:

response.setContentType("application/octet-stream;charset=ISO8859-1");
response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
response.addHeader("Pargam", "no-cache");
response.addHeader("Cache-Control", "no-cache");

设置response头信息,这几行注释掉,立马就好了,问题解决。

附上保存服务器代码段:

String path = request.getServletContext().getRealPath("/");//获取当前绝对路径
String dirsName = "test";//保存Excel的文件夹名称
String filename = "xxx.xlsx";//文件名
String resultPath = path  + dirName + filename;
File dirs = new File(path, dirsName);
if(!dirs.exists()) {
	dirs.mkdirs();//判断路径是否存在,不存在就创建
}
FileOutputStream fout = new FileOutputStream(resultPath);
wb.write(fout);//wb就是最终生成的Excel,写入到文件流中
fout.flush();
fout.close();

如果需要直接下载到本地电脑,可以加上下面这段代码,谷歌会直接保存到谷歌浏览器默认的下载地址,火狐会弹出提示框,提示用户保存或者打开。
附上代码段:

File f = new File(resultPath);//resultPath是服务器上的文件路径
if (!f.exists()) {
	response.sendError(404, "File not found!");
}
BufferedInputStream br = new BufferedInputStream(new FileInputStream(f));
byte[] buf = new byte[1024];
int len = 0;
//设置http response 头信息
response.reset();
response.setContentType("application/octet-stream;");  
response.setHeader("Content-Disposition", "attachment;filename="+ fileName);  
response.addHeader("Pargam", "no-cache");  
response.addHeader("Cache-Control", "no-cache");  
OutputStream out = response.getOutputStream();
while ((len = br.read(buf)) > 0) {
	out.write(buf, 0, len);
}
if (br != null)
	br.close();
if (out != null)
	out.close();

如果觉得我写的不好,可以看看这位大神的,复制出来就能用,链接:

http://www.cnblogs.com/crazyapple/p/5489588.html
插入图片详解:
http://blog.csdn.net/chenssy/article/details/20524563

下面是我导出excel的代码(导出一个Excel,包含多个sheet以及插入图片)

import java.io.IOException;
import java.util.List;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.ClientAnchor;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.apache.poi.xssf.usermodel.XSSFClientAnchor;
import org.apache.poi.xssf.usermodel.XSSFDrawing;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import sun.misc.BASE64Decoder;

public class ExcelUtil {

public static XSSFWorkbook getHSSFWorkbook(String[] sheetName,
		List<String[]> titleList, List<String[][]> valuesList,
		String[] img, XSSFWorkbook wb) throws IOException {
	// 第一步,创建一个webbook,对应一个Excel文件
	if (wb == null) {
		wb = new XSSFWorkbook();
	}
	// 第二步,在webbook中添加一个sheet,对应Excel文件中的sheet
	for (int i = 0; i < sheetName.length; i++) {
		XSSFSheet sheet = wb.createSheet(sheetName[i]);
		// 第三步,在sheet中添加表头第0行,注意老版本poi对Excel的行数列数有限制short
		XSSFRow row = sheet.createRow(0);
		// 第四步,创建单元格,并设置值表头 设置表头居中
		XSSFCellStyle style = wb.createCellStyle();
		style.setAlignment(HSSFCellStyle.ALIGN_CENTER); // 创建一个居中格式
		XSSFCell cell = null;

		for (int j = 0; j < titleList.get(i).length; j++) {
			cell = row.createCell(j);
			cell.setCellValue(titleList.get(i)[j]);
			cell.setCellStyle(style);
		}
		// 创建内容
		for (int y = 0; y < valuesList.get(i).length; y++) {
			row = sheet.createRow(y + 1);
			for (int f = 0; f < valuesList.get(i)[y].length; f++) {
				row.createCell(f).setCellValue(valuesList.get(i)[y][f]);
			}
		}
	
		if(img[i] != null){
			// 画图的顶级管理器,一个sheet只能获取一个(一定要注意这点)
			XSSFDrawing patriarch = sheet.createDrawingPatriarch();
			// anchor主要用于设置图片的属性

			ClientAnchor anchor = new XSSFClientAnchor(0, 0, 255, 255,
					(short) 0, valuesList.get(i).length + 2, (short) 10, 38);
			anchor.setAnchorType(3);

			BASE64Decoder decoder = new BASE64Decoder();
			
			byte[] decoderBytes = decoder.decodeBuffer(img[i]);
			patriarch
					.createPicture(anchor, wb.addPicture(decoderBytes,
							HSSFWorkbook.PICTURE_TYPE_PNG));
		}
	

	}

	return wb;
}
  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
### 回答1: POI是Apache下的一个开源项目,可以用来操作Excel文件。通过POI,可以很方便地在Excel中创建多个sheet页。可以使用Workbook.createSheet()方法创建新的sheet页,并可以使用Sheet.setSheetName()方法设置sheet页的名称。 ### 回答2: 随着poi的不断完善和发展,现在已经能够方便地实现导出excel文件的多个sheet页功能。 首先,我们需要导入poi的jar包,然后创建一个工作簿对象,即Workbook对象,这个对象负责创建我们要输出的Excel文件和其中的sheet页。 接着,我们可以创建多个sheet页,每个sheet页都是一个Sheet对象,我们可以使用Workbook的createSheet方法来创建一个sheet页,可以通过一个字符串来命名这个sheet页。 对于每个sheet页,我们可以使用同样的流程来设定表头、添加数据等操作。在所有数据都被填入sheet页之后,我们需要关闭输出流并保存文件,即调用workbook对象的write方法将数据写入文件中。 当然,要注意一些细节问题。比如,我们可以使用Workbook的setSheetName方法来给每个sheet页重命名,同时需要注意一些特殊字符的转义问题,如果表头和数据中包了这些特殊字符,需要进行转义才能正常显示。 以上就是poi导出excel多个sheet页的基本流程,需要注意的事项比较多,但使用起来还是比较方便的,特别适合一些需要导出大量数据的业务场景。 ### 回答3: poi是一种非常实用的Java API,可以帮助我们快速开发Excel导出功能。对于需要导出多个sheet页的需求,我们可以利用poi的工具类来实现。 首先,我们需要创建一个Workbook对象,表示整个Excel文件。然后,创建多个Sheet对象,表示每个sheet页。可以使用Workbook.createSheet()方法创建多个Sheet对象,并指定sheet页的名称。 接下来,我们需要创建行和单元格,向每个sheet页中写入数据。可以使用Sheet.createRow()方法创建行对象,然后使用Row.createCell()方法创建单元格对象,并设定单元格的值。 在写入数据之前,我们需要设置每个sheet页的列宽和样式。可以使用Sheet.setDefaultColumnWidth()方法设置列宽,使用CellStyle对象设置单元格的样式。 最后,我们需要将Workbook对象写入到文件中。可以使用FileOutputStream对象和Workbook.write()方法将Workbook对象写入到文件中。 总的来说,实现poi导出Excel多个sheet页需要以下步骤: 1.创建Workbook对象表示整个Excel文件; 2.创建多个Sheet对象表示每个sheet页; 3.设置每个sheet页的列宽和样式; 4.创建行和单元格,向每个sheet页中写入数据; 5.将Workbook对象写入到文件中。 使用poi导出Excel多个sheet页可以帮助我们提高开发效率,并满足不同的业务需求。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值