2000字范文,分享全网优秀范文,学习好帮手!
2000字范文 > 通过Java批量导出带有图片的Excel文件数据

通过Java批量导出带有图片的Excel文件数据

时间:2020-09-16 20:27:31

相关推荐

通过Java批量导出带有图片的Excel文件数据

批量导出带有图片的Excel文件

一、思路解析二、关键源码三、总结

Java通过POI或者一些常见的Excel工具类能够轻易导出后台的结构化数据,但是最近面临一个新需求,需要将对应记录数据和图片网络地址在同一行中导出。

一、思路解析

一般我们看到的Excel表格是这样的。

首先,我们考虑需要使用List存放每一行的值,并且规定第一行即为表头,从第二行开始是数据。

伪代码是这样的:

List<List<Object>> rowList = new ArrayList<List<Object>>();// Excel表头rowList.add(Arrays.asList("序号","标题", "图片"));for(int i=0;i<3;i++){// 每一行的数据rowList.add(Arrays.asList(i+1,"test"+(i+1),"imageUrl"+(i+1)));}// 调用生成Excel的方法ExcelUtils.toImportExcel(rowList);

唯一需要注意的是,跟一般的导出Excel方法不同的是,我们第三列的图片是一个网络URL地址,我们需要将其转成png或者img格式并嵌入到对应的Excel单元格里,这就是比较特别的地方,下文中会着重介绍。

二、关键源码

这里使用POI来解决问题,首先我们需要ExcelUtils工具类

public class ExcelUtils {/*** Excel导出设置Workbook* @param title 导出Excel文件名称* @param rowList 第一个List为表头,其余行为表数据* @param downLoadPic 是否下载图片* @throws IOException*/public static HSSFWorkbook warpSingleWorkbook(String title,List<List<Object>> rowList, Boolean downLoadPic) throws IOException {if (rowList == null || rowList.isEmpty()) {throw new NullPointerException("the row list is null");}HSSFWorkbook book = new HSSFWorkbook();// 创建表HSSFSheet sheet = book.createSheet(title);// 设置单元格默认宽度为20个字符sheet.setDefaultColumnWidth(20);HSSFPatriarch patriarch = sheet.createDrawingPatriarch();// 设置表头样式HSSFCellStyle style = book.createCellStyle();// 设置居左style.setAlignment(HSSFCellStyle.ALIGN_LEFT);// 检测表头数据(表头不允许数据为空)List<Object> head = rowList.get(0);// 写数据int size = rowList.get(0).size();// 第几行for (int i = 0; i < rowList.size(); i++) {List<Object> row = rowList.get(i);if (row == null || row.isEmpty()) {book.close();throw new NullPointerException("the "+(i+1)+"th row is null");}if (size != row.size()) {book.close();throw new IllegalArgumentException("the cell number of "+(i+1)+"th row is different form the first");}HSSFRow sr = sheet.createRow(i);// 第几列for (int j = 0; j < row.size(); j++) {// 如果是否下载照片选择了true,由于我们的照片放在第三列,即当循环到序列为2的时候获取到网络图片地址,这里还考虑到了有多张照片的情况,且用逗号拼接成多张照片。if (downLoadPic && i > 0 && j == 2) {if(StringUtils.isNotBlank(row.get(2).toString())){sr.setHeight((short) (1800));List<String> images = Arrays.asList(row.get(14).toString().split(","));int temp = j;for(String image : images){// 调用封装好的下载图片方法drawPictureInfoExcel(book, patriarch, i, j, image);j++;}}} else {setExcelValue(sr.createCell(j), row.get(j), style);}}}return book;}/*** 设置Excel浮点数可做金额等数据统计* @param cell 单元格类* @param value 传入的值*/public static void setExcelValue(HSSFCell cell, Object value, HSSFCellStyle style){// 写数据if (value == null) {cell.setCellValue("");}else {if (value instanceof Integer || value instanceof Long) {cell.setCellType(Cell.CELL_TYPE_NUMERIC);cell.setCellValue(Long.valueOf(value.toString()));} else if (value instanceof BigDecimal) {cell.setCellType(Cell.CELL_TYPE_NUMERIC);cell.setCellValue(((BigDecimal)value).setScale(3, RoundingMode.HALF_UP).doubleValue());} else {cell.setCellValue(value.toString());}cell.setCellStyle(style);}}/**** @param wb* @param patriarch* @param rowIndex* @param columnIndex* @param pictureUrl*/private static void drawPictureInfoExcel(HSSFWorkbook wb,HSSFPatriarch patriarch,int rowIndex, int columnIndex,String pictureUrl){//rowIndex代表当前行try {URL url = new URL(pictureUrl);//打开链接HttpURLConnection conn = (HttpURLConnection)url.openConnection();//设置请求方式为"GET"conn.setRequestMethod("GET");//超时响应时间为5秒conn.setConnectTimeout(5 * 1000);//通过输入流获取图片数据InputStream inStream = conn.getInputStream();//得到图片的二进制数据,以二进制封装得到数据,具有通用性byte[] data = readInputStream(inStream);//anchor主要用于设置图片的属性// dx1:起始单元格的x偏移量,// dy1:起始单元格的y偏移量,// dx2:终止单元格的x偏移量,// dy2:终止单元格的y偏移量,// col1:起始单元格列序号,从0开始计算;// row1:起始单元格行序号,从0开始计算,// col2:终止单元格列序号,从0开始计算;// row2:终止单元格行序号,从0开始计算,HSSFClientAnchor anchor = new HSSFClientAnchor(0, 0, 1023, 250,(short) columnIndex, rowIndex, (short) columnIndex, rowIndex);//Sets the anchor type (图片在单元格的位置)//0 = Move and size with Cells, 2 = Move but don't size with cells, 3 = Don't move or size with cells.anchor.setAnchorType(ClientAnchor.AnchorType.DONT_MOVE_AND_RESIZE);patriarch.createPicture(anchor, wb.addPicture(data, HSSFWorkbook.PICTURE_TYPE_PNG));} catch (IOException e) {e.printStackTrace();} catch (Exception e) {e.printStackTrace();}}private static byte[] readInputStream(InputStream inStream) throws Exception{ByteArrayOutputStream outStream = new ByteArrayOutputStream();//创建一个Buffer字符串byte[] buffer = new byte[1024];//每次读取的字符串长度,如果为-1,代表全部读取完毕int len = 0;//使用一个输入流从buffer里把数据读取出来while( (len=inStream.read(buffer)) != -1 ){//用输出流往buffer里写入数据,中间参数代表从哪个位置开始读,len代表读取的长度outStream.write(buffer, 0, len);}//关闭输入流inStream.close();//把outStream里的数据写入内存return outStream.toByteArray();}}

调用规则,从主入口进入方法,这里我们用下载蜡笔小新图片到Excel里为例,找到一张网络URL图片地址为:/timg?image&quality=80&size=b9999_10000&sec=1595325136781&di=2f03af92dfac5476b81ad22f426e76ad&imgtype=0&src=http%3A%2F%%2Fuploads%2Fitem%2F06%2F15%2F0615002128_eWXnf.jpeg

@ApiOperation(value = "带图片报表导出", notes = "带图片报表导出", httpMethod = "GET")@RequestMapping(value = "/importReport", method = RequestMethod.GET)public void importReport(HttpServletRequest req, HttpServletResponse res) {List<List<Object>> rowList = new ArrayList<List<Object>>();// Excel表头rowList.add(Arrays.asList("序号","标题", "图片"));for(int i=0;i<3;i++){// 下载三张蜡笔小新图片到Excel中rowList.add(Arrays.asList(i+1,"test"+(i+1),"/timg?image&quality=80&size=b9999_10000&sec=1595325136781&di=2f03af92dfac5476b81ad22f426e76ad&imgtype=0&src=http%3A%2F%%2Fuploads%2Fitem%2F06%2F15%2F0615002128_eWXnf.jpeg"));}// 接下来需要调用生成Excel的方法,唯一需要注意的是第三列的图片是一个网络URL地址,我们需要将其转成png或者img格式并嵌入到对应的Excel单元格里try {HSSFWorkbook wb = ExcelUtils.warpSingleWorkbook("带图片报表", rowList, true);res.reset();res.setHeader("Content-type","application/octet-stream");res.setContentType("application/octet-stream");res.setContentType("application/vnd.ms-excel");res.setHeader("Accept-Ranges", "bytes");String fileName = "带图片报表" + "_" + CalendarUtils.doFormatString(new Date(), CalendarUtils.YYYYMMDDHHmmss) + ".xls";fileName = new String(fileName.getBytes(), CommConstants.CHAESET_ZH);res.setHeader("Content-Disposition", "attachment;filename=" + fileName);// 文件流输出到rs里wb.write(res.getOutputStream());res.getOutputStream().flush();res.getOutputStream().close();wb.close();} catch (IOException e) {e.printStackTrace();}}

在网页端调用该方法后,导出的报表结果如下所示:

三、总结

唯一需要注意的是导出网络图片到Excel需要解析网络图片,且需要设置导出图片的单元格位置,在理清楚需求之后网上有许多已经造好的轮子可以复用。而时间充裕的话,建议大家可以去研究一下文中ExcelUtils工具类中的源码。

参考资料:

POI 导出excel 包含图片导出将图片导出到excel表格中

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。