如题,编程语言为java,利用Apache poi在服务器端生成带有数据和图片的excel的数据流至浏览器供其下载至本地,基本就是类似一个网站的数据导出功能。
主要参考网址:http://blog.csdn.net/sinat_22767969/article/details/50644648
基本主要代码是参考以上的网址的,本人在此基础上做了一些小的修改,就是使导出的图片呈比例的展示以及我本身的图片是从ftp上获取下来的,因此在插入的时候转换成字节流插入就好,还有就是自己根据自己所需生成表格的格式做些修改,这个就不明讲,自己看代码就好。
先说步骤:
1、把自己所要生成excel表格的数据统一存放进List表中,我这边是放一个实体类
2、在前端请求导出数据的时候, 再用自己已经生成号的List表数据去调用生成excel表格数据流传输至前方即可
3、前端最好用GET请求后台,这样前端可以直接调用后台该接口即可在浏览器完成下载,至于POST方法,本人没试成功,具体原因也不清楚。。。。
废话少说,show you code:
(1)设置excel的类
import java.awt.image.BufferedImage;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletResponse;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFClientAnchor;
import org.apache.poi.hssf.usermodel.HSSFFont;
import org.apache.poi.hssf.usermodel.HSSFPatriarch;
import org.apache.poi.hssf.usermodel.HSSFRichTextString;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import cn.recour.wiicop.db.entity.JYZTVio;//需要导出数据的实体类
/**
*
* @类名: ExportToExcelUtil
* @描述: 设置excel'的信息
*
*/
public class ExportToExcelUtil {
public static void out(HttpServletResponse response, List list,String fileName)
throws Exception {
/**
* 指定下载名
*/
// String fileName = "违停拍数据.xls";
/**
* 编码
*/
fileName = new String(fileName.getBytes("UTF-8"), "UTF-8");
/**
* 去除空白行
*/
response.reset();
/**
* 指定下载的文件名与设置相应头
*/
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "x-requested-with,Authorization");
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setCharacterEncoding("utf-8");
response.setHeader("Content-Disposition", "attachment;filename="
+ fileName);
/**
* 下载文件类型
*/
response.setContentType("application/vnd.ms-excel");
/**
* 别给我缓存
*/
response.setHeader("Pragma", "no-cache");
response.setHeader("Cache-Control", "no-cache");
response.setDateHeader("Expires", 0);
/**
* 得到输出流,放到缓冲区
*/
OutputStream output = response.getOutputStream();
BufferedOutputStream bufferedOutPut = new BufferedOutputStream(output);
/**
* 下面是导出的excel格式的设置
*/
/*******************我是分割线**************************************/
// 定义单元格报头
String worksheetTitle = "违停拍数据";
HSSFWorkbook wb = new HSSFWorkbook();
// 创建单元格样式
HSSFCellStyle cellStyleTitle = wb.createCellStyle();
// 指定单元格居中对齐
cellStyleTitle.setAlignment(HSSFCellStyle.ALIGN_CENTER);
// 指定单元格垂直居中对齐
cellStyleTitle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
// 指定当单元格内容显示不下时自动换行
cellStyleTitle.setWrapText(true);
HSSFCellStyle cellStyle = wb.createCellStyle();
// 指定单元格居中对齐
cellStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);
// 指定单元格垂直居中对齐
cellStyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
// 指定当单元格内容显示不下时自动换行
cellStyle.setWrapText(true);
// 设置单元格字体
HSSFFont font = wb.createFont();
font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
font.setFontName("宋体");
font.setFontHeight((short) 200);
cellStyleTitle.setFont(font);
/****************wo是分割线*****************************************/
/**
* 工作表列名
*/
String id = "序号";
String cphm = "车牌号码";
String location = "违停地址";
String time = "违停时间";
String img = "违停照片";
HSSFSheet sheet = wb.createSheet();
ExportExcelUtil exportExcel = new ExportExcelUtil(wb, sheet);
/**
* 创建报表头部
*/
exportExcel.createNormalHead(worksheetTitle, 4);
// 定义第一行
HSSFRow row1 = sheet.createRow(1);
HSSFCell cell1 = row1.createCell(0);
/**
* 第一行第一列
*/
cell1.setCellStyle(cellStyleTitle);
cell1.setCellValue(new HSSFRichTextString(id));
/**
* 第一行第二列
*/
cell1 = row1.createCell(1);
cell1.setCellStyle(cellStyleTitle);
cell1.setCellValue(new HSSFRichTextString(cphm));
/**
* 第一行第三列
*/
cell1 = row1.createCell(2);
cell1.setCellStyle(cellStyleTitle);
cell1.setCellValue(new HSSFRichTextString(location));
/**
* 第一行第四列
*/
cell1 = row1.createCell(3);
cell1.setCellStyle(cellStyleTitle);
cell1.setCellValue(new HSSFRichTextString(time));
/**
* 第一行第五列
*/
cell1 = row1.createCell(4);
cell1.setCellStyle(cellStyleTitle);
cell1.setCellValue(new HSSFRichTextString(img));
/********************我是分割线*********************************/
/**
* 定义第二行,就是我们的数据
*/
HSSFRow row = sheet.createRow(2);
HSSFCell cell = row.createCell(1);
sheet.setColumnWidth(4, 30 * 256);//固定图片宽度大小为30*256,然后在下面设置图片以此宽度为基准设置高度
/**
* 遍历我们传进来的jyztVio-list
*/
JYZTVio jyztVio =null;
HSSFPatriarch patriarch = sheet.createDrawingPatriarch();
for (int i = 0; i < list.size(); i++) {
jyztVio = list.get(i);
/**
* 从i+2行开始,因为我们之前的表的标题和列的标题已经占用了两行
*/
row = sheet.createRow(i + 2);
int s = i+1;
//...id
cell = row.createCell(0);
cell.setCellStyle(cellStyle);
cell.setCellValue(new HSSFRichTextString(s + ""));
//....车牌号码cphm
cell = row.createCell(1);
cell.setCellStyle(cellStyle);
cell.setCellValue(new HSSFRichTextString("\n"+jyztVio.getCphm()+"\n"));
//....违停地址
cell = row.createCell(2);
cell.setCellStyle(cellStyle);
cell.setCellValue(new HSSFRichTextString("\n"+jyztVio.getLocation()+"\n"));
//....违停时间
cell = row.createCell(3);
cell.setCellStyle(cellStyle);
cell.setCellValue(new HSSFRichTextString("\n"+jyztVio.getTime()+"\n"));
//...违停拍照
short h =2;//定义图片所在行
short l=4;//定义图片所在列
cell = row.createCell(4);
cell.setCellStyle(cellStyle);
//得到图片 new FileUtils().getFile(String path)这是我从ftp上获取图片的方法,里面参数是图片路径,各位具体情况具体处理
InputStream sbs = new ByteArrayInputStream(new FileUtils().getFile(jyztVio.getImage()));
BufferedImage image = ImageIO.read(sbs);
ByteArrayOutputStream byteArrayOut = new ByteArrayOutputStream();
int width = image.getWidth();//图片原始宽度
int height = image.getHeight();//图片原始高度
//根据宽度按比例设置高度
height = (int) Math.round((height * (30 * 13) * 1.0 / width));
row.setHeight((short) (height / 2 * 20));
ImageIO.write(image, "jpg", byteArrayOut);
HSSFClientAnchor anchor = new HSSFClientAnchor(0, 0, 0, 0, l, i + h, (short) (l+1), (i+1) + h);
anchor.setAnchorType(3);
// 插入图片
patriarch.createPicture(anchor, wb.addPicture(
byteArrayOut.toByteArray(),
HSSFWorkbook.PICTURE_TYPE_JPEG));
}
try {
/**
* 输出到浏览器
*/
bufferedOutPut.flush();
wb.write(bufferedOutPut);
bufferedOutPut.close();//关流
} catch (IOException e) {
e.printStackTrace();
} finally {
list.clear();
}
}
}
(2)excel导出的工具类
/**
* @author czy
* @version 创建时间:2017年10月31日 下午5:37:17
*
*/
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFFont;
import org.apache.poi.hssf.usermodel.HSSFRichTextString;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.hssf.util.Region;
/**
*
* @类名: ExportExcel
* @描述: excel工具类
*
*/
public class ExportExcelUtil {
private HSSFWorkbook wb = null;
private HSSFSheet sheet = null;
/**
*
*
* 标题:
*
*
* 描述:
*
*
* @param wb
* @param sheet
*/
public ExportExcelUtil(HSSFWorkbook wb, HSSFSheet sheet) {
// super();
this.wb = wb;
this.sheet = sheet;
}
/**
*
* @标题: createNormalHead
* @描述: TODO(这里用一句话描述这个方法的作用)
* @参数: @param headString 头部的字符
* @参数: @param colSum 报表的列数
* @返回: void 返回类型
* @抛出:
*/
@SuppressWarnings("deprecation")
public void createNormalHead(String headString, int colSum) {
HSSFRow row = sheet.createRow(0);
// 设置第一行
HSSFCell cell = row.createCell(0);
// row.setHeight((short) 1000);
// 定义单元格为字符串类型
cell.setCellType(HSSFCell.ENCODING_UTF_16);// 中文处理
cell.setCellValue(new HSSFRichTextString(headString));
// 指定合并区域
/**
* public Region(int rowFrom, short colFrom, int rowTo, short colTo)
*/
sheet.addMergedRegion(new Region(0, (short) 0, 0, (short) colSum));
// 定义单元格格式,添加单元格表样式,并添加到工作簿
HSSFCellStyle cellStyle = wb.createCellStyle();
// 设置单元格水平对齐类型
cellStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER); // 指定单元格居中对齐
cellStyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);// 指定单元格垂直居中对齐
cellStyle.setWrapText(true);// 指定单元格自动换行
// 设置单元格字体
HSSFFont font = wb.createFont();
font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
font.setFontName("宋体");
font.setFontHeight((short) 600);
cellStyle.setFont(font);
cell.setCellStyle(cellStyle);
}
/**
*
* @标题: createNormalTwoRow
* @描述: 创建通用报表第二行
* @参数: @param params 二行统计条件数组
* @参数: @param colSum 需要合并到的列索引
* @返回: void 返回类型
* @抛出:
*/
@SuppressWarnings("deprecation")
public void createNormalTwoRow(String[] params, int colSum) {
// 创建第二行
HSSFRow row1 = sheet.createRow(1);
row1.setHeight((short) 400);
HSSFCell cell2 = row1.createCell(0);
cell2.setCellType(HSSFCell.ENCODING_UTF_16);
cell2.setCellValue(new HSSFRichTextString("时间:" + params[0] + "至"
+ params[1]));
// 指定合并区域
sheet.addMergedRegion(new Region(1, (short) 0, 1, (short) colSum));
HSSFCellStyle cellStyle = wb.createCellStyle();
cellStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER); // 指定单元格居中对齐
cellStyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);// 指定单元格垂直居中对齐
cellStyle.setWrapText(true);// 指定单元格自动换行
// 设置单元格字体
HSSFFont font = wb.createFont();
font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
font.setFontName("宋体");
font.setFontHeight((short) 250);
cellStyle.setFont(font);
cell2.setCellStyle(cellStyle);
}
/**
*
* @标题: createColumHeader
* @描述: 设置报表标题
* @参数: @param columHeader 标题字符串数组
* @返回: void 返回类型
* @抛出:
*/
public void createColumHeader(String[] columHeader) {
// 设置列头 在第三行
HSSFRow row2 = sheet.createRow(2);
// 指定行高
row2.setHeight((short) 600);
HSSFCellStyle cellStyle = wb.createCellStyle();
cellStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER); // 指定单元格居中对齐
cellStyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);// 指定单元格垂直居中对齐
cellStyle.setWrapText(true);// 指定单元格自动换行
// 单元格字体
HSSFFont font = wb.createFont();
font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
font.setFontName("宋体");
font.setFontHeight((short) 250);
cellStyle.setFont(font);
// 设置单元格背景色
cellStyle.setFillForegroundColor(HSSFColor.GREY_25_PERCENT.index);
cellStyle.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
HSSFCell cell3 = null;
for (int i = 0; i < columHeader.length; i++) {
cell3 = row2.createCell(i);
cell3.setCellType(HSSFCell.ENCODING_UTF_16);
cell3.setCellStyle(cellStyle);
cell3.setCellValue(new HSSFRichTextString(columHeader[i]));
}
}
/**
*
* @标题: cteateCell
* @描述: 创建内容单元格
* @参数: @param wb HSSFWorkbook
* @参数: @param row HSSFRow
* @参数: @param col short型的列索引
* @参数: @param align 对齐方式
* @参数: @param val 列
* @返回: void 返回类型
* @抛出:
*/
public void cteateCell(HSSFWorkbook wb, HSSFRow row, int col, short align,
String val) {
HSSFCell cell = row.createCell(col);
cell.setCellType(HSSFCell.ENCODING_UTF_16);
cell.setCellValue(new HSSFRichTextString(val));
HSSFCellStyle cellstyle = wb.createCellStyle();
cellstyle.setAlignment(align);
cell.setCellStyle(cellstyle);
}
/**
*
* @标题: createLastSumRow
* @描述: 创建合计行
* @参数: @param colSum 需要合并到的列索引
* @参数: @param cellValue 设定文件
* @返回: void 返回类型
* @抛出:
*/
@SuppressWarnings("deprecation")
public void createLastSumRow(int colSum, String[] cellValue) {
HSSFCellStyle cellStyle = wb.createCellStyle();
cellStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER); // 指定单元格居中对齐
cellStyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);// 指定单元格垂直居中对齐
cellStyle.setWrapText(true);// 指定单元格自动换行
// 单元格字体
HSSFFont font = wb.createFont();
font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
font.setFontName("宋体");
font.setFontHeight((short) 250);
cellStyle.setFont(font);
// 获取工作表最后一行
HSSFRow lastRow = sheet.createRow((short) (sheet.getLastRowNum() + 1));
HSSFCell sumCell = lastRow.createCell(0);
sumCell.setCellValue(new HSSFRichTextString("合计"));
sumCell.setCellStyle(cellStyle);
// 合并 最后一行的第零列-最后一行的第一列
sheet.addMergedRegion(new Region(sheet.getLastRowNum(), (short) 0,
sheet.getLastRowNum(), (short) colSum));// 指定合并区域
for (int i = 2; i < (cellValue.length + 2); i++) {
// 定义最后一行的第三列
sumCell = lastRow.createCell(i);
sumCell.setCellStyle(cellStyle);
// 定义数组 从0开始。
sumCell.setCellValue(new HSSFRichTextString(cellValue[i - 2]));
}
}
/**
*
* @标题: outputExcel
* @描述: 输出excel下载
* @参数: @param fileName 文件名
* @返回: void 返回类型
* @抛出:
*/
public void outputExcel(String fileName) {
FileOutputStream fos = null;
try {
fos = new FileOutputStream(new File(fileName));
wb.write(fos);
fos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
*
* @返回: HSSFSheet 返回类型
*/
public HSSFSheet getSheet() {
return sheet;
}
public void setSheet(HSSFSheet sheet) {
this.sheet = sheet;
}
/**
*
* @返回: HSSFWorkbook 返回类型
*/
public HSSFWorkbook getWb() {
return wb;
}
/**
*
*/
public void setWb(HSSFWorkbook wb) {
this.wb = wb;
}
}
Controller层的代码:
/**
* 下载违停拍数据
* @param body
* @param request
* @param response
*/
@RequestMapping(value = "/downloaddata", method = RequestMethod.GET)
public @ResponseBody void downloaddata(HttpServletRequest request,HttpServletResponse response){
try {
String fileName = request.getParameter("fileName");
List jyztViolist = jyztVioService.downloaddata(request,response);
if(jyztViolist==null){
preJson(response,"无下载内容");
}else{
ExportToExcelUtil.out(response, jyztViolist, fileName);
}
} catch (Exception e) {
e.printStackTrace();
}
}
这样,前端只要调用该接口,就可以在浏览器完成下载功能。
注意:本人以上生成excel表和Excel工具类的代码基本是借鉴以上网址而来,只是根据自己功能需求做了一些改变,并没有想拿来做商业用途,如需要可删!
主要参考网址:http://blog.csdn.net/sinat_22767969/article/details/50644648