之前公司要用到xml导出word文档的报表,今天又是新需求,要poi导出excel文档的报表,所以我自己先查了资料(参照POI的官方文档),写了一个小的demo;具体步骤如下:
1、新建maven工程,引入POI的依赖:
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.9</version>
</dependency>
2、新建一个Customer的JavaBean,包含的字段自己定;
3、自己可以先做一个自己要做成一个什么样的报表的模板,比如我要做的就是如下的:
4、在页面上制作一个按钮,发送请求到servlet,servlet会调用controller层的代码,controller再调用导出excel的工具类;
具体代码如下:
servlet的代码:
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.chinacreator.c2.crm.utils.ExpwordUtils;
import com.chinacreator.c2.crm.utils.FilesUtil;
import com.chinacreator.c2.crm.web.rest.CustomerExpController;
public class ExpwordServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
// TODO Auto-generated method stub
doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
// TODO Auto-generated method stub
//接收页面传过来的type(导出的类型,1代表导出word 2代表导出excel
String type = req.getParameter("type");
String fileName = null;
String path = null;
//根据type判断,进行word还是excel的导出
if("1".equals(type)){
//word导出
//拦截用户的导出请求,进行权限的验证处理
//fileName = new ExpwordUtils().createWord();
fileName = new CustomerExpController().createWord();
path = this.getClass().getResource("/").getPath()+fileName + ".doc";
}else if("2".equals(type)){
//excel的导出
fileName = new CustomerExpController().createExcel();
path = this.getClass().getResource("/").getPath()+fileName + ".xls" ;
}
System.err.println("文件下载的路径是:"+path);
//用户下载文件
download(path, resp);
//删除临时文件的方法
FilesUtil.deleteFile(path);
}
//用户下载文件的方法
public void download(String path,HttpServletResponse response) throws IOException{
InputStream fis = null;
OutputStream toClient = null;
try {
// path是指欲下载的文件的路径。
File file = new File(path);
// 取得文件名。
String filename = URLEncoder.encode(file.getName(), "UTF-8");
// 以流的形式下载文件。
fis = new BufferedInputStream(new FileInputStream(path));
byte[] buffer = new byte[fis.available()];
fis.read(buffer);
//fis.close();
// 清空response
response.reset();
// 设置response的Header
response.addHeader("Content-Disposition", "attachment;filename=" + filename);
response.addHeader("Content-Length", "" + file.length());
toClient = new BufferedOutputStream(response.getOutputStream());
response.setContentType("application/vnd.ms-excel;charset=UTF-8");
toClient.write(buffer);
toClient.flush();
//toClient.close();
} catch (IOException ex) {
ex.printStackTrace();
}finally{
fis.close();
toClient.close();
}
}
}
controller的代码如下:
@Controller
@Path("customers/exp/")
@Consumes(MediaType.APPLICATION_JSON)
public class CustomerExpController {
/**
* word导出的方法
*/
@GET
@Path("wordexport")
public String createWord(){
// 根据自定义查询方法,查出数据
List<Customer> dataList = this.getData();
//获取文档标题
String titleName = "客户列表";
// 创建Excel,并写入文件
ExpwordUtils word = new ExpwordUtils();
word.createWord(titleName, dataList);
return titleName;
}
/**
* excel的导出方法
*/
@GET
@Path("excelexport")
public String createExcel(){
// 根据自定义查询方法,查出数据
List<Customer> dataList = this.getData();
//获取文档标题
String titleName = "客户列表";
// 创建Excel,并写入文件
ExpexcelUtils excel = new ExpexcelUtils();
excel.excelExport(titleName, dataList);
return titleName;
}
//查询数据的方法
private List<Customer> getData() {
//查询数据库得到导出的数据
List<Customer> customers = DaoFactory.create(Customer.class).selectAll();
return customers;
}
}
expexcelUtils的代码如下:/**
* java的POI导出excel的工具类
* @author ZDW
*
*/
public class ExpexcelUtils {
public String folderPath = this.getClass().getResource("/").getPath();
/**
* Excel导入准备工作
*/
public void excelExport(String titleName, List<Customer> dataList) {
/** 创建相关参数 */
// 第一行为文字描述
//String dataStr = div_text;
String dataStr = "客户信息描述:这里是今年的客户信息列表,里面包含了全部的客户,及所有客户的相关信息,比如:客户来源,客户行业,客户等级等";
// 第二行为大标题
String titleDate = titleName + " (截止" + new SimpleDateFormat("MM月dd日HH时").format(new Date()) + ")";
// 第三行,表头文字
String[] coloumItems1 = { "编号", "客户姓名", "客户来源", "客户行业", "客户等级","联系电话" };
// 第三行,上层表头坐标,顺序对应上层表头文字,重复的表头只存一个(对应的是行和列,四个数字对应:开始行,结束行,开始列,结束列)
String[] number1 = { "3,3,0,0", "3,3,1,1", "3,3,2,2", "3,3,3,3", "3,3,4,4", "3,3,5,5" };
// 开始写表格
writeExcel(dataStr, titleDate, coloumItems1, number1, dataList, titleName);
}
/**
* Excel写入数据
*
*/
private void writeExcel(String dataStr, String titleDate, String[] coloumItems1, String[] number1,
List<Customer> dataList, String title) {
// 创建文件
File file = new File(folderPath);
if (!file.exists()) {
file.mkdir();
}
FileOutputStream fileOutputStream = null;
try {
// 文件输出流
fileOutputStream = new FileOutputStream(folderPath + title + ".xls");
// 创建Excel设计样式
HSSFWorkbook workbook = new HSSFWorkbook();
// 获取列信息
HSSFSheet sheet = workbook.createSheet();
// 调整每列的列宽
sheet.setColumnWidth((short) 0, (short) 5 * 256);// 序号
sheet.setColumnWidth((short) 1, (short) 12 * 256);// 部门名称
//客户信息
sheet.setColumnWidth((short) 2, (short) 12 * 256);//
sheet.setColumnWidth((short) 3, (short) 12 * 256);//
sheet.setColumnWidth((short) 4, (short) 12 * 256);//
sheet.setColumnWidth((short) 5, (short) 15 * 256);//
// 设置第一行文字汇总
createTag1(workbook, sheet, dataStr);
// 设置第二行大标题
createTag2(workbook, sheet, titleDate);
// 设置第三行表头
createTag4(workbook, sheet, coloumItems1, number1);
// 设置表格内容
createValue(workbook, sheet, dataList);
// 开始写入数据
workbook.write(fileOutputStream);
// 关闭流
fileOutputStream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fileOutputStream != null) {
try {
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* 创建第一行的文字
*
* @param workbook
* @param sheet
* @param style
*/
private void createTag1(HSSFWorkbook workbook, HSSFSheet sheet, String dataStr) {
// 第一行,文字显示
sheet.addMergedRegion(new CellRangeAddress(0, 0, 0, 5));// 传入坐标,合并坐标内的单元格
HSSFRow row = sheet.createRow(0);// 获取第一行,作为文字汇总显示
row.setHeightInPoints(60);// 设置的值永远是height属性值的60倍
// 自定义该行样式
HSSFCellStyle styles = workbook.createCellStyle();
styles.setAlignment(HSSFCellStyle.ALIGN_LEFT);// 文本居左
styles.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);// 并垂直居中
styles.setWrapText(true);// 自动换行
// 设置字体
HSSFFont font = workbook.createFont();
font.setFontName("宋体");
font.setFontHeightInPoints((short) 12);// 设置字体大小
styles.setFont(font);
// 注意!如果要设置单行样式,必须cell和row都同时设置!
HSSFCell cell = row.createCell(0);
cell.setCellStyle(styles);
row.setRowStyle(styles);
// 写入文字数据
cell.setCellValue(" " + dataStr);
}
/**
* 创建第二行的大标题
*
* @param workbook
* @param sheet
* @param style
*/
private static void createTag2(HSSFWorkbook workbook, HSSFSheet sheet, String titleDate) {
// 第二行,大标题
sheet.addMergedRegion(new CellRangeAddress(1, 1, 0, 5));// 传入坐标,合并坐标内的单元格
HSSFRow row = sheet.createRow(1);// 获取第二行,作为总标题文字
row.setHeightInPoints(60);// 设置的值永远是height属性值的60倍
// 自定义该行样式
HSSFCellStyle styles = workbook.createCellStyle();
styles.setAlignment(HSSFCellStyle.ALIGN_CENTER); // 文本居中
styles.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);// 并垂直居中
// 设置字体
HSSFFont font = workbook.createFont();
font.setFontName("宋体");
font.setFontHeightInPoints((short) 12);// 设置字体大小
font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);// 粗体显示
styles.setFont(font);
// 注意!如果要设置单行样式,必须cell和row都同时设置!
HSSFCell cell = row.createCell(0);// 创建列
cell.setCellStyle(styles);// 设置表头样式
row.setRowStyle(styles);// 设置行样式
// 写入标题数据
cell.setCellValue(titleDate);
}
/**
* 创建第三、行的表格表头
*
* @param tags
* @param s
*/
private void createTag4(HSSFWorkbook workbook, HSSFSheet sheet, String[] coloumItems1, String[] number1) {
// 因为第三行为复杂合并行,自定义样式写在最上边
HSSFCellStyle styles = workbook.createCellStyle();
styles.setAlignment(HSSFCellStyle.ALIGN_CENTER);// 文本居中
styles.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);// 并垂直居中
styles.setWrapText(true);// 自动换行
// 设置边框
styles.setBorderBottom(HSSFCellStyle.BORDER_THIN); // 下边框
styles.setBorderLeft(HSSFCellStyle.BORDER_THIN);// 左边框
styles.setBorderTop(HSSFCellStyle.BORDER_THIN);// 上边框
styles.setBorderRight(HSSFCellStyle.BORDER_THIN);// 右边框
// 设置字体
HSSFFont font = workbook.createFont();
font.setFontName("宋体");
font.setFontHeightInPoints((short) 10);// 设置字体大小
font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);// 粗体显示
styles.setFont(font);
// 第三行,上层表头列名
HSSFRow row = sheet.createRow(2);// 获取第三行,作为上层的标头
row.setHeightInPoints(30);
// 该行样式注释的原因:因为要显示边框,如果行样式也设置,会导致Excel右边无关的表格也全显示边框,不好看
// row.setRowStyle(styles);
for (int i = 0; i < coloumItems1.length; i++) {
HSSFCell cell = row.createCell(i);
cell.setCellValue(coloumItems1[i]);
cell.setCellStyle(styles);
}
// 动态合并单元格
for (int i = 0; i < number1.length; i++) {
String[] temp = number1[i].split(",");
Integer startrow = Integer.parseInt(temp[0]);
Integer overrow = Integer.parseInt(temp[1]);
Integer startcol = Integer.parseInt(temp[2]);
Integer overcol = Integer.parseInt(temp[3]);
sheet.addMergedRegion(new CellRangeAddress(startrow, overrow, startcol, overcol));
}
}
/**
* 设置表格内容
*
* @param res
* @param s
*/
private void createValue(HSSFWorkbook workbook, HSSFSheet sheet, List<Customer> dataList) {
// 第五行开始循环写入表格数据,自定义样式同样写在上边
HSSFCellStyle styles = workbook.createCellStyle();
styles.setAlignment(HSSFCellStyle.ALIGN_CENTER);// 文本居中
styles.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);// 并垂直居中
styles.setWrapText(true);// 自动换行
// 设置边框
styles.setBorderBottom(HSSFCellStyle.BORDER_THIN); // 下边框
styles.setBorderLeft(HSSFCellStyle.BORDER_THIN);// 左边框
styles.setBorderTop(HSSFCellStyle.BORDER_THIN);// 上边框
styles.setBorderRight(HSSFCellStyle.BORDER_THIN);// 右边框
HSSFRow row = null;
HSSFCell cell = null;
int count = dataList.size();
for (int i = 0; i < count; i++) {
Customer customer = dataList.get(i);
row = sheet.createRow(i + 3);// 从第四行开始
// 该行样式注释的原因:因为要显示边框,如果行样式也设置,会导致Excel右边无关的表格也全显示边框,不好看
// row.setRowStyle(styles);
// 设置行高
row.setHeightInPoints(30);// 设置的值永远是height属性值的30倍
cell = row.createCell(0);
cell.setCellStyle(styles);
cell.setCellValue(Double.parseDouble(customer.getCustId()+""));
cell = row.createCell(1);
cell.setCellStyle(styles);
cell.setCellValue(customer.getCustName());
cell = row.createCell(2);
cell.setCellStyle(styles);
cell.setCellValue(customer.getCustSource());
cell = row.createCell(3);
cell.setCellStyle(styles);
cell.setCellValue(customer.getCustIndustry());
cell = row.createCell(4);
cell.setCellStyle(styles);
cell.setCellValue(customer.getCustLevel());
cell = row.createCell(5);
cell.setCellStyle(styles);
cell.setCellValue(customer.getCustMobile());
}
}
}