Java中带图片的数据导出到excel

本文介绍了如何在Java中利用POI和EasyExcel库导出包含图片的Excel文件。提供了无图片导出和带图片导出的实现方式,并详细讲解了数据映射和图片处理的步骤。同时,提到了模板下载和图片数据导入的相关资源。
摘要由CSDN通过智能技术生成

导入带图片的excel,可查看文章:Java 通过POI快速导入带图片的excel并且图片不会丢失

数据导出

导出包含了带图片的与不带图片的导出方式,大致如下:

  1. 无图片的导出
    这种导出可以选择你喜欢用的,POI或者EasyExcel等,这里选用的EasyExcel。
    引入依赖:
<!-- 阿里 easyexcel -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>easyexcel</artifactId>
            <version>2.2.4</version>
            <exclusions>
                <exclusion>
                    <artifactId>poi-ooxml</artifactId>
                    <groupId>org.apache.poi</groupId>
                </exclusion>
            </exclusions>
        </dependency>

接口数据查询及表格映射导出:

@PostMapping("exportBridgesData")
    public void exportBridgesData(HttpServletResponse response,
                                  HttpServletRequest request,
                                  @RequestBody UrbanListQueryDto dto){
        //导出数据获取,注意数据与抬头的映射
        List<RoadsAndBridgesExportVo> vos = urbanManageListService.exportRoadsAndBridgesData(dto, Constants.MAINTAIN);
        if(CollectionUtils.isEmpty(vos)){
            throw new ServiceException("暂无数据可导出!");
        }
        ExcelUtil.writeExcel(response,request, vos, "列表.xlsx", "列表", RoadsAndBridgesExportVo.class);
    }

数据映射截图:
在这里插入图片描述
这里使用的导出调用的方法:

/**
     * 导出Excel(一个sheet)
     *
     * @param response  HttpServletResponse
     * @param list      数据list
     * @param fileName  导出的文件名
     * @param sheetName 导入文件的sheet名
     * @param clazz 实体类
     */
    public static <T> void  writeExcel(HttpServletResponse response, HttpServletRequest request,
                                       List<T> list, String fileName, String sheetName, Class<T> clazz) {
        OutputStream outputStream = handleRequestResponse(response, request, fileName);
        EasyExcel.write(outputStream, clazz).sheet(sheetName).doWrite(list);
    }

这是个工具类,很多方法可以查看详细参数介绍官网

  1. 带图片的导出
package com.yfjgpt.disposalCompany.utils;

import com.alibaba.fastjson.JSONObject;
import org.apache.poi.ss.usermodel.ClientAnchor;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.Picture;
import org.apache.poi.ss.usermodel.VerticalAlignment;
import org.apache.poi.xssf.usermodel.*;
import org.springblade.core.tool.utils.DateUtil;
import org.springblade.core.tool.utils.Func;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.net.URL;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Description:
 * @author: guo-xz
 * @Project:
 * @Date: 2022年08月11日 09:16
 */
public class ExcelUtilImpl{

	//这里可以根据自己情况修改,本地修改后图片放在后面了,下面也有参数说明
	
	/**
	 *  导出
	 *
	 * @param list 数据列表
	 * @param excelHeaders 表头
	 * @param keys 导出字段属性
	 * @param fileName 文件名称
	 * @param response 相应对象
	 * @return
	 */
	public static void excelImg(List<Map> list, String[] excelHeaders, String[] keys, String fileName, HttpServletResponse response){
		excelImg(list, excelHeaders, keys, null, fileName, response);
	}

	/**
	 *  导出
	 *
	 * @param list 数据列表
	 * @param excelHeaders 表头
	 * @param keys 导出字段属性
	 * @param imgs 导出图片字段属性,用逗号隔开
	 * @param fileName 文件名称
	 * @param response 相应对象
	 * @return
	 */
	public static void excelImg(List<Map> list, String[] excelHeaders, String[] keys, String imgs, String fileName, HttpServletResponse response){
		// 获取数据列表
		// 创建一个工作簿,对应文件
		XSSFWorkbook workBook = new XSSFWorkbook();
		// 创建一个sheet工作表
		XSSFSheet sheet = workBook.createSheet(fileName + DateUtil.time());
		// 设置表头单元格样式
		XSSFCellStyle headstyle = workBook.createCellStyle();
		// 设置居中
		headstyle.setAlignment(HorizontalAlignment.CENTER);
		headstyle.setVerticalAlignment(VerticalAlignment.CENTER);
		XSSFFont headFont = workBook.createFont();
		headFont.setFontHeight(14);
		headFont.setBold(true);
		headstyle.setFont(headFont);

		// 创建一般单元格样式
		XSSFCellStyle cellstyle = workBook.createCellStyle();
		cellstyle.setAlignment(HorizontalAlignment.CENTER);
		cellstyle.setVerticalAlignment(VerticalAlignment.CENTER);
		cellstyle.setWrapText(true);
		XSSFFont cellFont = workBook.createFont();
		cellFont.setFontHeight(11);
		cellstyle.setFont(cellFont);
		XSSFRow headRow = sheet.createRow(0);
		for (int i = 0; i < excelHeaders.length; i++) {
			XSSFCell cell = headRow.createCell(i);
			cell.setCellValue(excelHeaders[i]);
			cell.setCellStyle(headstyle);
			sheet.setColumnWidth(i, (20 * 256));
		}
		// 创建内容
		XSSFRow row = null;
		for (int rowIndex = 0; rowIndex < list.size(); rowIndex++) {
			row = sheet.createRow(rowIndex + 1);
			row.setHeight((short) (40 * 20));
			// 单元格
			XSSFCell cell = null;
			String s = JSONObject.toJSONString(list.get(rowIndex));
			// 转成map
			Map<String,Object> map = JSONObject.parseObject(s, HashMap.class);
			for (int j = 0; j < keys.length; j++) {
				cell = row.createCell(j);
				cell.setCellStyle(cellstyle);
				if(Func.isNotEmpty(imgs) && imgs.contains((String)map.get(keys[j]))){
					cell.setCellValue("");
					try{
						URL photoFile = new URL( (String) map.get(keys[j]));
						// 先把读进来的图片放到一个ByteArrayOutputStream中,以便产生ByteArray
						ByteArrayOutputStream byteArrayOut = new ByteArrayOutputStream();
						//将图片读入BufferedImage对象
						BufferedImage bufferImg = ImageIO.read(photoFile);
						// 将图片写入流中
						ImageIO.write(bufferImg, "jpg", byteArrayOut);
						// 利用HSSFPatriarch将图片写入EXCEL
						XSSFDrawing patriarch = sheet.createDrawingPatriarch();
						// 图片一导出到单元格I3-5中 列开始:8 行开始:2 列结束:9 行结束:5
						XSSFClientAnchor anchor = new XSSFClientAnchor(0, 0, 0, 0, j, rowIndex + 1, j, rowIndex + 1);
						anchor.setAnchorType(ClientAnchor.AnchorType.MOVE_AND_RESIZE);
						// 插入图片内容
						Picture picture =  patriarch.createPicture(anchor, workBook.addPicture(byteArrayOut
							.toByteArray(), XSSFWorkbook.PICTURE_TYPE_JPEG));
						picture.resize(1.05,1.10);
						//将图片插入工作表
					}catch (Exception e) {
						cell.setCellValue("暂无图片");
					}
				}else{
					cell.setCellValue((String) map.get(keys[j]));
				}
			}
		}
		try {
			//最终已流的形式返回
			OutputStream out = null;
			out = response.getOutputStream();
			response.setHeader("content-type", "application/octet-stream");
			response.setContentType("application/octet-stream");
			response.addHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(fileName + DateUtil.time() + ".xlsx", "UTF-8"));
			workBook.write(out);
			out.flush();
			out.close();
		}catch (Exception e) {
			e.printStackTrace();
		}
	}
}

这是我修改后封装的公用方法,第一个为数据列表,第二个是T,也就是导出的数据类,这里是通过前面的T的@ExcelRow来获取判断字段是否是图片字段,是就进行图片的列设置
在这里插入图片描述

在这里插入图片描述

本地封装好的放下面了:

 /**
     *  导出
     *
     * @param list 数据列表
     * @param clazz 映射体
     * @param smallTitle 需要指定的小标题,位于数据列名行之上
     * @param fileName 文件名称
     * @param response 相应对象
     * @return
     */
    public void excelImg(List<T> list, @NotNull final Class<?> clazz, String smallTitle, String fileName, HttpServletResponse response){
        //获取文件属性
        ExcelFile excelFile = clazz.getAnnotation(ExcelFile.class);
        //获取是否导出图片列
        List<Integer> pictureCloum = new ArrayList<>();
        //获取字段及表头
        List<String> formatterText = new ArrayList<>();
        Map<Integer, Object> title = getTitle(clazz, formatterText, pictureCloum);

        // 获取数据列表
        // 创建一个工作簿,对应文件
        XSSFWorkbook workBook = new XSSFWorkbook();
        // 创建一个sheet工作表
        XSSFSheet sheet = workBook.createSheet(fileName);
        // 设置表头单元格样式
        XSSFCellStyle headstyle = workBook.createCellStyle();
        // 设置居中
        setCenter(workBook, headstyle);
        // 创建一般单元格样式
        XSSFCellStyle cellstyle = workBook.createCellStyle();
        createCellstyle(workBook, cellstyle);


        int rowNum = 0;
        //创建标题
        if (null != excelFile) {
            rowNum = createHead(excelFile, sheet, rowNum, workBook, formatterText, cellstyle);
        }
        if(StringUtils.isNotEmpty(smallTitle)){
            rowNum = createSmallHead(smallTitle, sheet, rowNum, workBook, formatterText, cellstyle);
        }
        //创建列标题
        rowNum = createCloumTitle(sheet, title, headstyle, rowNum);
        // 创建内容
        for (int rowIndex = 0; rowIndex < list.size(); rowIndex++) {
            rowNum = rowNum + 1;
            XSSFRow row = sheet.createRow(rowNum);
            row.setHeight((short) (40 * 20));
            // 单元格
            XSSFCell cell = null;
            String s = JSONObject.toJSONString(list.get(rowIndex));
            // 转成map
            Map<String,Object> map = JSONObject.parseObject(s, HashMap.class);
            for (int j = 0; j < formatterText.size(); j++) {
                cell = row.createCell(j);
                cell.setCellStyle(cellstyle);
                Object obj = map.get(formatterText.get(j));
                String value = null;
                if(ObjectUtils.isNotEmpty(obj)){
                    value = String.valueOf(obj);
                }
                if(!CollectionUtils.isEmpty(pictureCloum) && pictureCloum.contains(j)){
                    try{
                        if(StringUtils.isNotEmpty(value)){
                            putPicture(value, workBook, sheet, rowNum, j);
                        }
                    }catch (Exception e) {
                        cell.setCellValue("暂无图片");
                    }
                }else{
                    if(StringUtils.isNotEmpty(value)){
                        cell.setCellValue(value);
                    }
                }
            }
        }
        try {
            //最终已流的形式返回
            OutputStream out = null;
            out = response.getOutputStream();
            response.setHeader("content-type", "application/octet-stream");
            response.setContentType("application/octet-stream");
            response.addHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(fileName + DateUtil.format(new Date(), "yyyy-MM-dd") + ".xlsx", "UTF-8"));
            workBook.write(out);
            out.flush();
            out.close();
        }catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void createCellstyle(XSSFWorkbook workBook, XSSFCellStyle cellstyle){
        // 创建一般单元格样式
        cellstyle.setAlignment(HorizontalAlignment.CENTER);
        cellstyle.setVerticalAlignment(VerticalAlignment.CENTER);
        cellstyle.setWrapText(true);
        XSSFFont cellFont = workBook.createFont();
        cellFont.setFontHeight(11);
        cellstyle.setFont(cellFont);
    }

    /**
     * @description: 设置属性值居中
     * @param: [workBook, headstyle]
     * @return: void
     * @date: 2022/9/6 14:39
     * @version: 1.0
     **/
    private void setCenter(XSSFWorkbook workBook, XSSFCellStyle headstyle){
        headstyle.setAlignment(HorizontalAlignment.CENTER);
        headstyle.setVerticalAlignment(VerticalAlignment.CENTER);
        XSSFFont headFont = workBook.createFont();
        headFont.setFontHeight(14);
        headFont.setBold(true);
        headstyle.setFont(headFont);
    }

    /**
     * @description: 创建大标题
     * @param: [excelFile]
     * @return: void
     * @date: 2022/9/6 14:54
     * @version: 1.0
     **/
    private Integer createHead(ExcelFile excelFile, XSSFSheet sheet, int rowNum, XSSFWorkbook wb, List<String> formatterText, XSSFCellStyle cellstyle){
        int endCloum = formatterText.size() - 1;
        String bigTitle = excelFile.bigTitle();
        String description = excelFile.description();
        int x = excelFile.x();
        int y = excelFile.y();
        if(StringUtils.isNotEmpty(bigTitle)){
            XSSFRow row = sheet.createRow(rowNum);
            row.setHeight((short) (40 * 20));
            //设置标题头
            //----------------标题样式--------------------------------
            XSSFCellStyle titleStyle = createTitleStyle(wb);
            XSSFCell cell = row.createCell(0);
            cell.setCellValue(bigTitle);
            cell.setCellStyle(titleStyle);
            sheet.addMergedRegion(new CellRangeAddress(rowNum, rowNum, 0, endCloum));
            rowNum = rowNum + 1;
        }
        if(StringUtils.isNotEmpty(description)){
            XSSFRow row = sheet.createRow(rowNum);
            row.setHeight((short) (40 * 20));
            if(x != 0){
                XSSFCell cell = row.createCell(x);
                cell.setCellValue(description);
                cell.setCellStyle(cellstyle);
            }else {
                XSSFCell cell = row.createCell(formatterText.size());
                cell.setCellValue(description);
                cell.setCellStyle(cellstyle);
            }
            if(y != 0){
                sheet.addMergedRegion(new CellRangeAddress(rowNum, rowNum, x, y));
            }else{
                sheet.addMergedRegion(new CellRangeAddress(rowNum, rowNum, x, endCloum));
            }
            rowNum = rowNum + 1;
        }
        return rowNum;
    }

    /**
     * @description: 创建小标题
     * @param: [excelFile, row, sheet, rowNum, wb, formatterText, cellstyle]
     * @return: void
     * @date: 2022/9/6 15:48
     * @version: 1.0
     **/
    private Integer createSmallHead(String smallTitle, XSSFSheet sheet, int rowNum, XSSFWorkbook wb, List<String> formatterText, XSSFCellStyle cellstyle){
        XSSFRow row = sheet.createRow(rowNum);
        row.setHeight((short) (40 * 20));
        XSSFCell cell = row.createCell(0);
        cell.setCellValue(smallTitle);
        cell.setCellStyle(cellstyle);
        sheet.addMergedRegion(new CellRangeAddress(rowNum, rowNum, 0, formatterText.size() -1));
        //创建一行给列标题用
        rowNum = rowNum + 1;
        return rowNum;
    }

    private Integer createCloumTitle(XSSFSheet sheet, Map<Integer, Object> title, XSSFCellStyle headstyle, int rowNum) {
        XSSFRow headRow = sheet.createRow(rowNum);
        for (int i = 0; i < title.size(); i++) {
            XSSFCell cell = headRow.createCell(i);
            cell.setCellValue(String.valueOf(title.get(i)));
            cell.setCellStyle(headstyle);
            sheet.setColumnWidth(i, (20 * 256));
        }
        return rowNum;
    }

    /**
     * @description: 创建标题样式
     * @param: [wb]
     * @return: org.apache.poi.xssf.usermodel.XSSFCellStyle
     * @date: 2022/9/6 15:47
     * @version: 1.0
     **/
    private XSSFCellStyle createTitleStyle(XSSFWorkbook wb){
        //标题样式
        XSSFCellStyle titleStyle = wb.createCellStyle();
        titleStyle.setAlignment(HorizontalAlignment.CENTER);
        titleStyle.setVerticalAlignment(VerticalAlignment.CENTER);
        Font ztFont = wb.createFont();
        ztFont.setItalic(false); // 设置字体为斜体字
        //ztFont.setColor(Font.COLOR_NORMAL);            // 将字体设置为“红色”
        ztFont.setFontHeightInPoints((short) 16); // 将字体大小设置为18px
        ztFont.setFontName("宋体"); // 将“宋体”字体应用到当前单元格上
        ztFont.setBold(true); //加粗
        //ztFont.setUnderline(Font.U_DOUBLE);// 添加(Font.U_SINGLE单条下划线/Font.U_DOUBLE双条下划线)
        //ztFont.setStrikeout(true);// 是否添加删除线
        titleStyle.setFont(ztFont);
        return titleStyle;
    }

    /**
     * @description: 获取标题行及需要的特殊字段
     * @param: [clazz, formatterText, pictureCloum]
     * @return: java.util.Map<java.lang.Integer,java.lang.Object>
     * @date: 2022/9/6 11:11
     * @version: 1.0
     **/
    private Map<Integer, Object> getTitle(Class<?> clazz, List<String> formatterText, List<Integer> pictureCloum){
        Field[] fields = getAllField(clazz);
        Map<Integer, Object> title = new HashMap<>();
        for (Field field : fields) {
            ExcelRow excelRow = field.getAnnotation(ExcelRow.class);
            if (excelRow != null) {
                title.put(excelRow.columnNo(), excelRow.cloumName());
                formatterText.add(field.getName());
                if(excelRow.isPicture()){
                    pictureCloum.add(excelRow.columnNo());
                }
            }
        }
        return title;
    }

    private Field[] getAllField(Class<?> clazz) {
        //获取对象及其父类所有属性
        Field[] fields = null;
        //newObject是传入对象
        for (; clazz != Object.class; clazz = clazz.getSuperclass()) {//向上循环 遍历父类
            Field[] field = clazz.getDeclaredFields();
            //hutool工具包,合并两个数组
            fields = ArrayUtil.addAll(fields, field);
        }
        return fields;
    }

    /**
     * @description: 图片设置
     * @param: [pictureUrl, workBook, sheet, rowIndex, j]
     * @return: void
     * @date: 2022/9/6 11:17
     * @version: 1.0
     **/
    private void putPicture(String pictureUrl, XSSFWorkbook workBook, XSSFSheet sheet, int rowIndex, int j) throws Exception{
        URL photoFile = new URL(pictureUrl);
        // 先把读进来的图片放到一个ByteArrayOutputStream中,以便产生ByteArray
        ByteArrayOutputStream byteArrayOut = new ByteArrayOutputStream();
        //将图片读入BufferedImage对象
        BufferedImage bufferImg = ImageIO.read(photoFile);
        // 将图片写入流中,后缀可获取url后的后缀
        ImageIO.write(bufferImg, "jpeg", byteArrayOut);
        // 利用HSSFPatriarch将图片写入EXCEL
        XSSFDrawing patriarch = sheet.createDrawingPatriarch();
        // 图片一导出到单元格I3-5中 列开始:8 行开始:2 列结束:9 行结束:5
        XSSFClientAnchor anchor = new XSSFClientAnchor(0, 0, 0, 0, j, rowIndex, j, rowIndex);
        anchor.setAnchorType(ClientAnchor.AnchorType.MOVE_AND_RESIZE);
        // 插入图片内容
        Picture picture =  patriarch.createPicture(anchor, workBook.addPicture(byteArrayOut
                .toByteArray(), XSSFWorkbook.PICTURE_TYPE_JPEG));
        picture.resize(1.05,1.10);
        //将图片插入工作表
    }

需要查看模板下载及resource下的模板下载,可查看文章:模板下载
需要excel图片信息等数据导入,可查看文章:Java带图片的excel数据导入

死鬼~看完了来个三连哦!O.O`
在这里插入图片描述

反手就是一个赞赞赞——————————奥里给

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

焚目圣僧渡众生

你的 一角将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值