最近接收了一个做数据报表的一个系统,一堆奇葩的需求。数据报表嘛,都会涉及数据导出各式各样的excel,话不多说,上教程
1,poi的XSSFWorkbook
XSSFWorkbook:是操作Excel2007的版本,扩展名是.xlsx,千万不要用错了如果你用的是HSSFWorkbook扩展名不是.xl会报错;
上代码:
XSSFWorkbook wb = new XSSFWorkbook();
// sheet页名称
XSSFSheet sheet = wb.createSheet(sheetName);
sheet.autoSizeColumn(1, true);
sheet.createRow(0).setHeight((short) 800);// 首行高度
XSSFRow row = sheet.createRow(0);
//row.setHeightInPoints(40);
XSSFCellStyle style = this.getColumnTopStyle(wb);
// 第一个参数代表列id(从0开始),第2个参数代表宽度值
sheet = ExcelTemplate.getHeadSheet(sheet, heads.length);
// 冻结首行
sheet.createFreezePane(0, 1, 0, 1);
// 获取模板
///XSSFCell cell = ExcelTemplate.getHeadCall(row, style, heads);
//这里我进行了数据处理的一个封装
ExcelTemplate.exportTemplateImg( row, sheet,heads, style,this.getStyle(wb), collect , multipartfiles,courseIds,wb);
封装段里面的数据处理是根据我的业务需求来设计的可以与其他的人的不符合:
XSSFCell cell = row.createCell(0);
Integer count = 0;
for (Integer courseId : courseIds) {
for (int j = 0; j < heads.length; j++) {
row = sheet.getRow(1);
if (null == row) {
//如果不做空判断,你必须让你的模板文件画好边框,beginRow和beginCell必须在边框最大值以内
//否则会出现空指针异常
row = sheet.createRow(1);
}
cell = row.createCell(count + j);
cell.setCellValue(heads[j]);
cell.setCellStyle(style);
}
List<PlanImgExcelVO> list = collect.get(courseId);
for (int i = 0; i < list.size(); i++) {
PlanImgExcelVO vo = list.get(i);
if (!VerifyUtil.isEmpty(vo.getAimName())) {
row = sheet.getRow(0);
cell = row.createCell(count + 0);
cell.setCellValue(vo.getAimName());
cell.setCellStyle(style);
}
row = sheet.getRow(i + 2);
if (null == row) {
//如果不做空判断,你必须让你的模板文件画好边框,beginRow和beginCell必须在边框最大值以内
//否则会出现空指针异常
row = sheet.createRow(i + 2);
}
cell = row.createCell(count + 0);
cell.setCellValue(vo.getFinishDate());
cell.setCellStyle(style1);
cell = row.createCell(count + 1);
cell.setCellValue(vo.getPlanNum());
cell.setCellStyle(style1);
cell = row.createCell(count + 2);
cell.setCellValue(vo.getFinishNum());
cell.setCellStyle(style1);
}
//合并数据格(首行,末行,首列,末列)
CellRangeAddress region = new CellRangeAddress(0, 0, count + 0, count + 2);
sheet.addMergedRegion(region);
count += 4;
}
这里有一个小提示,是否有需要生成数据是根据数据类型进行导入excel,就是在一个数据列的后面列再去插入数据,如图: 这样的数据格式
首先我们来看,一般我们插入都是一个list集合,
for (int i = 1; i < list.size() + 1; i++) {
row = sheet.createRow((int) i);
TestVO vo = list.get(i - 1);
cell = row.createCell(0);
cell.setCellValue(i);
cell.setCellStyle(style);
cell = row.createCell(1);
cell.setCellValue(vo.getProjectNum());
cell.setCellStyle(style);
cell = row.createCell(2);
cell.setCellValue(vo.getProjectName());
cell.setCellStyle(style);
cell = row.createCell(3);
cell.setCellValue(vo.getName());
cell.setCellStyle(style);
row = sheet.createRow((int) i);这个代码就是创建单元行,这样的方式试用与单个list且数据横向添加,我们现在是要的纵向的如上图那样,我是这样设计的,既然我们都创建的行,我在获取出来行不,row = sheet.getRow(i);获取行的代码,这样获取它的行再添加就不会出现重复行创建之前的数据没有了的情况,
row = sheet.getRow(i + 2);
if (null == row) {
//如果不做空判断,你必须让你的模板文件画好边框,beginRow和beginCell必须在边框最大值以内
//否则会出现空指针异常
row = sheet.createRow(i + 2);
}
如果不做空判断,你必须让你的模板文件画好边框,beginRow和beginCell必须在边框最大值以内,否则会出现空指针异常。
以上是数据处理,接下来图片功能。
public void exportExcelImg(HttpServletRequest request, HttpServletResponse response,@RequestBody PlanImgFindExcelDTO dto) throws IOException {
MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
List<MultipartFile> multipartfiles = multipartRequest.getFiles("images");
//先把读进来的图片放到一个ByteArrayOutputStream中,以便产生ByteArray
ByteArrayOutputStream byteArrayOut = new ByteArrayOutputStream();
// String imageUrlHead = PropertiesUtils.getProperty("IMAGE_URL_HEAD");
//创建一个excel文件,名称为:
XSSFWorkbook workbook = new XSSFWorkbook();
//创建一个sheet,名称为工作簿1
XSSFSheet sheet = workbook.createSheet("工作簿1");
//画图的顶级管理器,一个sheet只能获取一个(一定要注意这点)
XSSFDrawing patriarch = sheet.createDrawingPatriarch();
//anchor主要用于设置图片的属性
/* XSSFClientAnchor anchor = new XSSFClientAnchor(0, 0, 0, 0, (short) 2, 2, (short) 4, 4);
anchor.setAnchorType(ClientAnchor.MOVE_AND_RESIZE);*/
Integer col1 = 0;
if (multipartfiles != null)) {
//先把读进来的图片放到一个ByteArrayOutputStream中,以便产生ByteArray
ByteArrayOutputStream byteArrayOut = new ByteArrayOutputStream();
//画图的顶级管理器,一个sheet只能获取一个(一定要注意这点)
XSSFDrawing patriarch = sheet.createDrawingPatriarch();
Integer col1 = 0;
for (MultipartFile file : multipartfiles) {
Map<String, Object> map = new HashMap<String, Object>();
// 文件名
String originalFilename = file.getOriginalFilename();
// 文件扩展名
String fileExtName = originalFilename.substring(originalFilename.lastIndexOf(".") + 1);
// 文件流
InputStream inputStream = file.getInputStream();
XSSFClientAnchor anchor = new XSSFClientAnchor(0, 0, 0, 0, col1, 8, col1 + 4, 12);
patriarch.createPicture(anchor, wb.addPicture(inputStream, XSSFWorkbook.PICTURE_TYPE_PNG));
col1 = col1 + 2;
}
/* FileOutputStream fileOutputStream = new FileOutputStream("F://demo2.xlsx");
workbook.write(fileOutputStream);*/
OutputStream output = response.getOutputStream();
response.reset();
response.setHeader("Content-Type", "application/vnd.ms-excel;charset=UTF-8");
response.setContentType("application/msexcel");
response.setHeader("Content-disposition", "attachment; filename=" + "demo2.xlsx" );
workbook.write(output);
output.flush();
output.close();
}
没有啥难点介绍,就是前段传入的图片我们转成文件流在写入,这个逻辑相对不复杂易上手,主要的要主要: new XSSFClientAnchor(0, 0, 0, 0, col1, 0, col1+2, 4); 这个是处理图片位置和大小的。
图片加数据两者合起来的样子就是
XSSFCell cell = row.createCell(0);
Integer count = 0;
for (Integer courseId : courseIds) {
for (int j = 0; j < heads.length; j++) {
row = sheet.getRow(1);
if (null == row) {
//如果不做空判断,你必须让你的模板文件画好边框,beginRow和beginCell必须在边框最大值以内
//否则会出现空指针异常
row = sheet.createRow(1);
}
cell = row.createCell(count + j);
cell.setCellValue(heads[j]);
cell.setCellStyle(style);
}
List<PlanImgExcelVO> list = collect.get(courseId);
for (int i = 0; i < list.size(); i++) {
PlanImgExcelVO vo = list.get(i);
if (!VerifyUtil.isEmpty(vo.getAimName())) {
row = sheet.getRow(0);
cell = row.createCell(count + 0);
cell.setCellValue(vo.getAimName());
cell.setCellStyle(style);
}
row = sheet.getRow(i + 2);
if (null == row) {
//如果不做空判断,你必须让你的模板文件画好边框,beginRow和beginCell必须在边框最大值以内
//否则会出现空指针异常
row = sheet.createRow(i + 2);
}
cell = row.createCell(count + 0);
cell.setCellValue(vo.getFinishDate());
cell.setCellStyle(style1);
cell = row.createCell(count + 1);
cell.setCellValue(vo.getPlanNum());
cell.setCellStyle(style1);
cell = row.createCell(count + 2);
cell.setCellValue(vo.getFinishNum());
cell.setCellStyle(style1);
}
CellRangeAddress region = new CellRangeAddress(0, 0, count + 0, count + 2);
sheet.addMergedRegion(region);
count += 4;
}
if (!VerifyUtil.isEmpty(multipartfiles)) {
//先把读进来的图片放到一个ByteArrayOutputStream中,以便产生ByteArray
ByteArrayOutputStream byteArrayOut = new ByteArrayOutputStream();
// String imageUrlHead = PropertiesUtils.getProperty("IMAGE_URL_HEAD");
//画图的顶级管理器,一个sheet只能获取一个(一定要注意这点)
XSSFDrawing patriarch = sheet.createDrawingPatriarch();
//anchor主要用于设置图片的属性
/* XSSFClientAnchor anchor = new XSSFClientAnchor(0, 0, 0, 0, (short) 2, 2, (short) 4, 4);
anchor.setAnchorType(ClientAnchor.MOVE_AND_RESIZE);*/
Integer col1 = 0;
for (MultipartFile file : multipartfiles) {
Map<String, Object> map = new HashMap<String, Object>();
// 文件名
String originalFilename = file.getOriginalFilename();
// 文件扩展名
String fileExtName = originalFilename.substring(originalFilename.lastIndexOf(".") + 1);
// 文件流
InputStream inputStream = file.getInputStream();
BufferedImage bufferedImage = ImageIO.read(inputStream);
ImageIO.write(bufferedImage, fileExtName, byteArrayOut);
XSSFClientAnchor anchor = new XSSFClientAnchor(0, 0, 0, 0, col1, 8, col1 + 4, 12);
anchor.setAnchorType(ClientAnchor.MOVE_AND_RESIZE);
col1 = col1 + 2;
//插入图片
patriarch.createPicture(anchor, wb.addPicture(byteArrayOut.toByteArray(), XSSFWorkbook.PICTURE_TYPE_JPEG));
}
}
}
这个就不介绍了。就这样了