[Excel] Verwenden Sie SpringBoot zum Importieren und Exportieren von Excel-Dateien

Damit jeder diesen Blog-Beitrag besser versteht, wird empfohlen, vor dem Lesen meinen letzten Blog-Beitrag zu lesen: [Datei] Verwenden Sie SpringBoot zum Hoch- und Herunterladen von Dateien . Denn dieser Blogbeitrag ist eine Fortsetzung des vorherigen Blogbeitrags.

Diese beiden Blogbeiträge hängen miteinander zusammen: Der Import von Dateien ist das Hochladen von Dateien; der Export von Dateien ist das Herunterladen von Dateien.

Warum Excel-Dateien importieren/exportieren? Weil Excel-Dateien häufiger verwendet werden. Sehen wir uns übrigens noch einmal an, wie EasyExcelman Excel-Dateien über verwaltet.

Codierungsideen:

Excel-Import:

  1. Durchsuchen Sie den Ordner und wählen Sie die Excel-Datei aus, die hochgeladen werden soll. Verwenden Sie hier das POSTMAN-Tool.
  2. Lokale Dateien an den angegebenen Speicherort auf dem Server hochladen;
  3. Der Server analysiert die Excel-Datei.
  4. Speichern Sie die in Excel analysierten Daten in der Datenbank.

Excel-Export

  1. Abfragebedingungen festlegen;
  2. Fragen Sie die entsprechenden Daten in der Datenbank ab;
  3. Daten in Excel schreiben;
  4. Laden Sie Excel auf den lokalen Computer herunter.

POM-Abhängigkeiten importieren:

<dependency>
  <groupId>com.alibaba</groupId>
  <artifactId>easyexcel</artifactId>
  <version>3.2.1</version>
</dependency>

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.5</version>
</dependency>

1. Excel-Import

FileController: Importschnittstelle hinzufügen

@RestController
@RequestMapping("/file")
public class FileController {
    
    

    @Autowired
    private FileService fileService;

    @PostMapping("/importExcel")
    public ResultVo importExcel(@RequestParam("file") MultipartFile excel) {
    
    
        return fileService.importExcel(excel);
    }

}

FileServiceImpl::

@Service
@Slf4j
public class FileServiceImpl implements FileService {
    
    

    @Autowired
    private ExcelUtil excelUtil;

    @Override
    public ResultVo importExcel(MultipartFile file) {
    
    
        // 1.可做入参校验,这里省略
        // 2.上传至服务器某路径下
        ResultVo resultVo = uploadFile(file);
        if (!resultVo.checkSuccess()) {
    
    
            return resultVo;
        }
        String filePath = (String)resultVo.getData();
        if (StringUtil.isBlank(filePath)) {
    
    
            return ResultVoUtil.error("【导入Excel文件】生成的Excel文件的路径为空");
        }
        // 3.读取excel文件
        List<ExcelVo> excelVos = excelUtil.simpleExcelRead(filePath, ExcelVo.class);
        if (CollectionUtil.isEmpty(excelVos) || excelVos.size() < 2) {
    
    
            log.error("【导入Excel文件】上传Excel文件{}为空", file.getOriginalFilename());
            return ResultVoUtil.error("上传Excel文件为空");
        } 
        // 4.删除临时文件
        boolean deleteFile = FileUtil.deleteFile(new File(filePath));
        if (!deleteFile) {
    
    
            log.error("【导入Excel文件】删除临时文件失败,临时文件路径为{}", filePath);
            return ResultVoUtil.error("删除临时文件失败");
        }
        log.info("【导入Excel文件】删除临时文件成功,临时文件路径为:{}", filePath);
        return ResultVoUtil.success(excelVos);
    }
	
	// 上传文件
	public ResultVo<String> uploadFile(MultipartFile file) {
    
    
        log.info("【文件上传】进入到文件上传方法");
        // 1.参数校验
        if (null == file || file.isEmpty()) {
    
    
            log.error("【文件上传】文件为空!");
            throw new ParamErrorException();
        }
        // 2.上传文件
        ResultVo<String> resultVo = FileUtil.uploadFile(file);
        return resultVo;
    }
    
}
public class FileUtil {
    
    

    // 下划线
    public static final String UNDER_LINE = "_";

    // 上传文件
    public static ResultVo<String> uploadFile(MultipartFile file) {
    
    
        // 1.获取一个新的文件名
        String newFileName = getNewFileName(file);
        if (StringUtil.isBlank(newFileName)) {
    
    
            log.error("【上传文件】转换文件名称失败");
            return ResultVoUtil.error("【上传文件】转换文件名称失败");
        }
        // 2.获取文件上传路径
        String uploadPath = "E:\\temp";
        if (StringUtil.isBlank(uploadPath)) {
    
    
            log.error("【上传文件】获取文件上传路径失败");
            return ResultVoUtil.error("【上传文件】获取文件上传路径失败");
        }
        uploadPath = uploadPath + File.separator +  DateUtil.getCurrentDate();
        // 3.生成上传目录
        File uploadDir = mkdirs(uploadPath);
        if (!uploadDir.exists()) {
    
    
            log.error("【上传文件】生成上传目录失败");
            return ResultVoUtil.error("【上传文件】生成上传目录失败");
        }
        // 4.文件全路径
        String fileFullPath = uploadPath + File.separator + newFileName;
        log.info("上传的文件:" + file.getName() + "," + file.getContentType() + ",保存的路径为:" + fileFullPath);
        try {
    
    
            // 5.上传文件
            doUploadFile(file, fileFullPath);
        } catch (IOException e) {
    
    
            log.error("【上传文件】上传文件报IO异常,异常信息为{}", e.getMessage());
            return ResultVoUtil.error(e.getMessage());
        }
        return ResultVoUtil.success(fileFullPath);
    }

    /**
     * @Description:上传文件
     * @Author: zzc
     * @Date: 2021-11-11 0:05
     * @param file:
     * @param path:
     * @return: void
     **/
    public static void doUploadFile(MultipartFile file, String path) throws IOException {
    
    
        // 法一:
        Streams.copy(file.getInputStream(), new FileOutputStream(path), true);

        // 法二: 通过MultipartFile#transferTo(File)
        // 使用此方法保存,必须要绝对路径且文件夹必须已存在,否则报错
        //file.transferTo(new File(path));

        // 法三:通过NIO将字节写入文件
        //Path filePath = Paths.get(path);
        //Files.write(filePath, file.getBytes());

        // 法四:
        /*try (InputStream in = file.getInputStream();
             FileOutputStream out = new FileOutputStream(path)) {
            IOUtils.copy(in, out);
        } catch (Exception e) {
            log.error("【上传文件】上传文件失败,失败信息为:{}", e.getMessage());
        }*/

        // 法五:
        /*InputStream in = file.getInputStream();
        OutputStream out = new FileOutputStream(path);
        int len = 0;
        byte[] bytes = new byte[1024];
        while ((len = in.read(bytes)) != -1) {
            out.write(bytes, 0, len);
        }
        in.close();
        out.close();*/

        // 法六:
        /*byte[] bytes = file.getBytes();
        OutputStream out = new FileOutputStream(path);
        out.write(bytes);
        out.close();*/
    }

    /**
     * @Description:递归生成父级路径
     * @Author: zzc
     * @Date: 2021-11-10 23:55
     * @param path:
     * @return: void
     **/
    public static File mkdirs(String path) {
    
    
        File file = new File(path);
        if(!file.exists() || !file.isDirectory()) {
    
    
            file.mkdirs();
        }
        return file;
    }

    /**
     * @Description:将上传的文件转换为一个新的文件名
     * @Author: zzc
     * @Date: 2021-11-10 23:17
     * @param file:
     * @return: java.lang.String
     **/
    public static String getNewFileName(MultipartFile file) {
    
    
        // 1.获取上传的文件名称(包含后缀。如:test.jpg)
        String originalFilename = file.getOriginalFilename();
        log.info("【上传文件】上传的文件名为{}", originalFilename);
        // 2.以小数点进行分割
        String[] split = originalFilename.split("\\.");
        String newFileName = null;
        if (null == split || split.length == 0) {
    
    
            return null;
        }
        StringBuilder builder = new StringBuilder();
        if (1 == split.length) {
    
    
            // 3.此文件无后缀
            newFileName = builder.append(originalFilename).append(UNDER_LINE).append(System.nanoTime()).toString();
            return newFileName;
        }
        // 4.获取文件的后缀
        String fileSuffix = split[split.length - 1];
        for (int i = 0; i < split.length - 1; i++) {
    
    
            builder.append(split[i]);
            if (null != split[i + 1] && "" != split[i + 1]) {
    
    
                builder.append(UNDER_LINE);
            }
        }
        newFileName = builder.append(System.nanoTime()).append(".").append(fileSuffix).toString();
        return newFileName;
    }

    /**
     * @Description:下载文件
     * @Author: zzc
     * @Date: 2021-11-12 0:01
     * @param file:
     * @param response:
     * @return: com.zzc.hardcore.vo.ResultVo<java.lang.String>
     **/
    public static ResultVo<String> downloadFile(File file, HttpServletResponse response) {
    
    
        try {
    
    
            // 1.设置响应头
            setResponse(file, response);
        } catch (UnsupportedEncodingException e) {
    
    
            log.error("文件名{}不支持转换为字符集{}", file.getName(), "UTF-8");
            return ResultVoUtil.error(e.getMessage());
        }
        // 2.下载文件
        return doDownLoadFile(file, response);
    }

    /**
     * @Description:下载文件
     * @Author: zzc
     * @Date: 2021-11-11 22:51
     * @param file:
     * @param response:
     * @return:
     **/
    public static ResultVo<String> doDownLoadFile(File file, HttpServletResponse response) {
    
    
        // 法一:IOUtils
        /*try (FileInputStream in = new FileInputStream(file);
             OutputStream out = response.getOutputStream()) {
            // 2.下载文件
            IOUtils.copy(in, out);
            log.info("【文件下载】文件下载成功");
            return null;
        } catch (FileNotFoundException e) {
            log.error("【文件下载】下载文件时,没有找到相应的文件,文件路径为{}", file.getAbsolutePath());
            return ResultVoUtil.error(e.getMessage());
        } catch (IOException e) {
            log.error("【文件下载】下载文件时,出现文件IO异常");
            return ResultVoUtil.error(e.getMessage());
        }*/

        // 法二:将文件以流的形式一次性读取到内存,通过响应输出流输出到前端
        /*try (InputStream in = new BufferedInputStream(new FileInputStream(file));
             OutputStream out = new BufferedOutputStream(response.getOutputStream())) {
            byte[] buffer = new byte[in.available()];
            in.read(buffer);
            out.write(buffer);
            log.info("【文件下载】文件下载成功");
            return null;
        } catch (IOException e) {
            log.error("【文件下载】下载文件时,出现文件IO异常");
            return ResultVoUtil.error(e.getMessage());
        }*/

        // 法三:将输入流中的数据循环写入到响应输出流中,而不是一次性读取到内存,通过响应输出流输出到前端
        try (InputStream in = new FileInputStream(file);
             OutputStream out = response.getOutputStream()) {
    
    
            byte[] buffer = new byte[1024];
            int len = 0;
            while ((len = in.read(buffer)) != -1) {
    
    
                out.write(buffer, 0, len);
            }
            log.info("【文件下载】文件下载成功");
            return null;
        } catch (FileNotFoundException e){
    
    
            log.error("【文件下载】下载文件时,没有找到相应的文件,文件路径为{}", file.getAbsolutePath());
            return ResultVoUtil.error(e.getMessage());
        } catch (IOException e) {
    
    
            log.error("【文件下载】下载文件时,出现文件IO异常");
            return ResultVoUtil.error(e.getMessage());
        }
    }

    /**
     * @Description:设置响应头
     * @Author: zzc
     * @Date: 2021-11-11 22:44
     * @param file:
     * @param response:
     * @return: void
     **/
    public static void setResponse(File file, HttpServletResponse response) throws UnsupportedEncodingException {
    
    
        // 清空response
        response.reset();
        response.setCharacterEncoding("UTF-8");
        // 返回给客户端类型,任意类型
        response.setContentType("application/octet-stream");
        // Content-Disposition的作用:告知浏览器以何种方式显示响应返回的文件,用浏览器打开还是以附件的形式下载到本地保存
        // attachment表示以附件方式下载 inline表示在线打开 "Content-Disposition: inline; filename=文件名.mp3"
        response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(file.getName(), "UTF-8"));
        // 告知浏览器文件的大小
        response.addHeader("Content-Length", String.valueOf(file.length()));
    }

    /**
     * @Description:递归删除目录下的所有文件及子目录下所有文件
     * @Author: zzc
     * @Date: 2021-11-14 18:34
     * @param file:
     * @return: boolean
     **/
    public static boolean deleteFile(File file) {
    
    
        if (!file.exists()) {
    
    
            return false;
        }
        if (file.isDirectory()) {
    
    
            String[] children = file.list();
            //递归删除目录中的子目录下
            for (int i=0; i<children.length; i++) {
    
    
                boolean success = deleteFile(new File(file, children[i]));
                if (!success) {
    
    
                    return false;
                }
            }
        }
        // 目录此时为空,可以删除
        return file.delete();
    }

    /**
     * @Description:获取文件下载时生成文件的路径
     * @Author: zzc
     * @Date: 2021-11-14 19:25
     * @return: java.lang.String
     **/
    public static String getDownLoadPath() {
    
    
        return fileConfig.getDownloadPath();
    }

}

veranschaulichen:

  1. List<ExcelVo> excelVos = excelUtil.simpleExcelRead(filePath, ExcelVo.class);Sie geben mir einen Excel-Dateipfad und einen Datentyp, und ich kann die Daten in dieser Excel-Datei in einer Sammlung kapseln und an Sie zurücksenden;

ExcelUtil::

@Component
@Slf4j
public class ExcelUtil<T> {
    
    

    // excel文件后缀
    private final static String EXCE_L2003 = "xls";
    private final static String EXCEL_2007 = "xlsx";

    // 校验文件后缀是否为 xls、xlsx
    public static boolean checkExcelExtension(MultipartFile excel) {
    
    
        String filename = excel.getOriginalFilename();
        if (StringUtil.isBlank(filename)) {
    
    
            log.info("【校验Excel文件后缀】Excel文件名为空");
            return false;
        }
        int index = filename.lastIndexOf(".");
        if (index == -1) {
    
    
            log.info("【校验Excel文件后缀】Excel文件名中没有点号");
            return false;
        }
        String extension = filename.substring(index + 1);
        return Arrays.asList(EXCE_L2003, EXCEL_2007).contains(extension);
    }

    // 读取excel文件
    public List<T> simpleExcelRead(String filePath, Class<T> clazz) {
    
    
        ExcelListener<T> excelListener = new ExcelListener();
        EasyExcel.read(filePath, clazz, excelListener).sheet().doRead();
        List<T> dataList = excelListener.getDataList();
        return dataList;
    }

}

veranschaulichen:

  1. EasyExcel.read(filePath, clazz, excelListener).sheet().doRead();Ruft ExcelListenerdie Methode in der Klasse auf und speichert die gelesenen Daten in dataList der Sammlung.
  2. Die Klasse hier ExcelUtilverwendet Generika. Sie können jede Art von Daten übergeben, die Sie importieren möchten. Was ich hier importiere, ist ExcelVoTyp.

ExcelListener::

@Slf4j
public class ExcelListener<T> extends AnalysisEventListener<T> {
    
    

    // 返回读取到的excel中的数据
    List<T> dataList = new ArrayList<>();

    public ExcelListener() {
    
    
    }

    // 每一条数据解析都会来调用
    @Override
    public void invoke(T t, AnalysisContext analysisContext) {
    
    
        log.info("【Excel文件】解析到一条数据{}:", JSON.toJSONString(t));
        dataList.add(t);
    }

    // 所有数据解析完成了 才会来调用
    @Override
    public void doAfterAllAnalysed(AnalysisContext analysisContext) {
    
    
        log.info("【Excel文件】Excel所有数据解析完毕!");
    }

    public List<T> getDataList() {
    
    
        return dataList;
    }
}

ExcelVo: Vorlage für Dateninformationen in Excel

@Data
@NoArgsConstructor
@AllArgsConstructor
public class ExcelVo {
    
    
	// 姓名
    private String name;
    // 性别 1:女 0:男
    @ExcelProperty(converter = SexConvert.class)
    private Integer sex;
    // 创建时间
    @DateTimeFormat("yyyy年MM月dd日HH时mm分ss秒")
    private String createTime;

}

veranschaulichen:

  1. Eigenschaften in ExcelVo entsprechen Excel-Dateien
  2. Für das Geschlechtsattribut verwenden wir einen Konverter. Das Geschlecht in der Excel-Datei entspricht männlich und weiblich, aber wir müssen die plastischen Zahlen 0 und 1 verwenden, um es zu erhalten, also müssen wir einen Geschlechtsumrechner anpassen

Excel-Inhalt:
Fügen Sie hier eine Bildbeschreibung ein
SexConvert:Geschlechtsumrechner

public class SexConvert implements Converter<Integer> {
    
    

    @Override
    public Class supportJavaTypeKey() {
    
    
        return Integer.class;
    }

    @Override
    public CellDataTypeEnum supportExcelTypeKey() {
    
    
        return CellDataTypeEnum.STRING;
    }

    // 这里读的时候会调用
    @Override
    public Integer convertToJavaData(CellData cellData, ExcelContentProperty excelContentProperty, GlobalConfiguration globalConfiguration) throws Exception {
    
    
        switch (cellData.getStringValue()) {
    
    
            case "男":
                return 0;
            case "女":
                return 1;
            default:
                return 0;
        }
    }

    // 这里写的时候会调用
    @Override
    public CellData convertToExcelData(Integer integer, ExcelContentProperty excelContentProperty, GlobalConfiguration globalConfiguration) throws Exception {
    
    
        switch (integer) {
    
    
            case 1:
                return new CellData("女");
            case 0:
                return new CellData("男");
            default:
                return new CellData(String.valueOf(integer));
        }
    }

}

FileUtil.deleteFile(): Temporäre Dateien löschen

// 递归删除目录下的所有文件及子目录下所有文件
public static boolean deleteFile(File file) {
    
    
    if (!file.exists()) {
    
    
        return false;
    }
    if (file.isDirectory()) {
    
    
        String[] children = file.list();
        //递归删除目录中的子目录下
        for (int i=0; i<children.length; i++) {
    
    
            boolean success = deleteFile(new File(file, children[i]));
            if (!success) {
    
    
                return false;
            }
        }
    }
    // 目录此时为空,可以删除
    return file.delete();
}

2. Excel-Export

FileController: Dateiexportschnittstelle hinzufügen

@PostMapping("/exportExcel")
public ResultVo exportExcel(final HttpServletResponse response) {
    
    
    return fileService.exportExcel(response);
}

FileServiceImpl::

@Override
public ResultVo<String> exportExcel(HttpServletResponse response) {
    
    
    // 1.根据查询条件获取结果集
    List<ExcelWriteVo> excelWriteVos = getExcelWriteVoListByCondition();
    if (CollectionUtil.isEmpty(excelWriteVos)) {
    
    
        log.info("【导出Excel文件】要导出的数据为空,无法导出!");
        return ResultVoUtil.success("数据为空");
    }
    // 2.获取要下载Excel文件的路径
    ResultVo<String> resultVo = getDownLoadPath(ExcelWriteVo.class, excelWriteVos);
    if (!resultVo.checkSuccess()) {
    
    
        log.error("【导出Excel文件】获取要下载Excel文件的路径失败");
        return resultVo;
    }
    // 3.下载Excel文件
    String fileDownLoadPath = resultVo.getData();
    ResultVo<String> downLoadResultVo = downloadFile(fileDownLoadPath, response);
    if (null != downLoadResultVo && !downLoadResultVo.checkSuccess()) {
    
    
        log.error("【导出Excel文件】下载文件失败");
        return downLoadResultVo;
    }
    // 4.删除临时文件
    boolean deleteFile = FileUtil.deleteFile(new File(fileDownLoadPath));
    if (!deleteFile) {
    
    
        log.error("【导入Excel文件】删除临时文件失败,临时文件路径为{}", fileDownLoadPath);
        return ResultVoUtil.error("删除临时文件失败");
    }
    log.info("【导入Excel文件】删除临时文件成功,临时文件路径为:{}", fileDownLoadPath);
    return null;
}

getExcelWriteVoListByCondition(): Rufen Sie die zu exportierenden Daten basierend auf Bedingungen ab

Dies sollte über die Datenbank abgefragt werden, ich verwende hier jedoch direkt gefälschte Daten.

public List<ExcelWriteVo> getExcelWriteVoListByCondition() {
    
    
    List<ExcelWriteVo> excelWriteVos = new ArrayList<>(5);
    excelWriteVos.add(new ExcelWriteVo("zzc", "男", "2021-11-14 20:00:00"));
    excelWriteVos.add(new ExcelWriteVo("wzc", "女", "2021-11-14 20:00:00"));
    excelWriteVos.add(new ExcelWriteVo("wxc", "男", "2021-11-14 20:00:00"));
    return excelWriteVos;
}

ExcelWriteVo :Excel-Datei exportiert die entsprechende Vo-Klasse

@Data
@NoArgsConstructor
@AllArgsConstructor
public class ExcelWriteVo {
    
    

    // 姓名
    @ExcelProperty("姓名")
    private String name;

    // 性别 1:女 0:男
    @ExcelProperty("性别")
    private String sex;

    // 创建时间
    @DateTimeFormat("yyyy年MM月dd日HH时mm分ss秒")
    @ExcelProperty("创建时间")
    private String createTime;

}

Exportiertes Excel:
Fügen Sie hier eine Bildbeschreibung ein

getDownLoadPath(): Rufen Sie den Pfad zum Herunterladen der Excel-Datei ab

public ResultVo<String> getDownLoadPath(Class<ExcelWriteVo> clazz, List<ExcelWriteVo> excelWriteVos) {
    
    
    String downLoadPath = FileUtil.getDownLoadPath();
    if (StringUtil.isBlank(downLoadPath)) {
    
    
        log.error("【导出Excel文件】生成临时文件失败");
        return ResultVoUtil.error("生成临时文件失败");
    }
    // 1.创建一个临时目录
    FileUtil.mkdirs(downLoadPath);
    String fullFilePath = downLoadPath + File.separator + System.currentTimeMillis() + "." + ExcelUtil.EXCEL_2007;
    log.info("【导出Excel文件】文件的临时路径为:{}", fullFilePath);
    // 2.写入数据
    excelUtil.simpleExcelWrite(fullFilePath, clazz, excelWriteVos);
    return ResultVoUtil.success(fullFilePath);
}

application.yml: Beim Herunterladen der Datei wurde ein Pfad zum Generieren der Datei hinzugefügt

file:
  uploadPath: E:/upload
  downloadPath: E:/download

FileUtil::

// 获取文件下载时生成文件的路径
public static String getDownLoadPath() {
    
    
    return fileConfig.getDownloadPath();
}

ExcelUtil::

@Slf4j
public class ExcelUtil<T> {
    
    

    // excel文件后缀
    public final static String EXCE_L2003 = "xls";
    public final static String EXCEL_2007 = "xlsx";

    // sheet名字
    public final static String SHEET_NAME = "模板";
	
	// 写Excel文件
	public void simpleExcelWrite(String filePath, Class<T> clazz, List<T> dataList) {
    
    
        EasyExcel.write(filePath, clazz).sheet(SHEET_NAME).doWrite(dataList);
    }
    
}

Nun, das ist alles für die Bedienung von Excel über EasyExcel-Dateien.

=============================================== =======================================
2021-12-07 Update:

Verwenden Sie easyexcel, um Hyperlink- oder Anhangsadressen festzulegen

Referenzadresse

POM-Abhängigkeit ändern: geänderte easyexcelVersion. 2.0.0-beta2Version kann nicht importiert werdenAbstractCellWriteHandler

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>easyexcel</artifactId>
    <version>2.2.6</version>
</dependency>

ExcelWriteVo: Fügen Sie ein Feld zur Darstellung von Anhängen hinzu

@Data
@NoArgsConstructor
@AllArgsConstructor
public class ExcelWriteVo {
    
    
	// ...
	
	// 附件
    private String photo;
}

FileServiceImpl#getExcelWriteVoListByCondition(): Ändern Sie die Konstruktionsmethode

public List<ExcelWriteVo> getExcelWriteVoListByCondition() {
    
    
    List<ExcelWriteVo> excelWriteVos = new ArrayList<>(5);
    excelWriteVos.add(new ExcelWriteVo("zzc", "男", "2021-11-14 20:00:00", "附件1"));
    excelWriteVos.add(new ExcelWriteVo("wzc", "女", "2021-11-14 20:00:00", "附件1"));
    excelWriteVos.add(new ExcelWriteVo("wxc", "男", "2021-11-14 20:00:00", "附件1"));
    return excelWriteVos;
}

Fügen Sie einen Prozessor hinzu PhotoHandler:

@Slf4j
public class PhotoHandler extends AbstractCellWriteHandler {
    
    

    @Override
    public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, List<CellData> cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {
    
    
        // 这里可以对cell进行任何操作
        log.info("第{}行,第{}列写入完成。", cell.getRowIndex(), cell.getColumnIndex());
        if (isHead && cell.getColumnIndex() == 0) {
    
     // 对第一行第一列的头超链接
            CreationHelper createHelper = writeSheetHolder.getSheet().getWorkbook().getCreationHelper();
            Hyperlink hyperlink = createHelper.createHyperlink(HyperlinkType.URL);
            hyperlink.setAddress("https://github.com/alibaba/easyexcel");
            cell.setHyperlink(hyperlink);
        }
        if (!isHead && head.getFieldName().equals("photo")) {
    
     // 头为 photo 的列设置附件地址
            CreationHelper createHelper = writeSheetHolder.getSheet().getWorkbook().getCreationHelper();
            Hyperlink hyperlink = createHelper.createHyperlink(HyperlinkType.FILE); // 类型设置为 FILE
            hyperlink.setAddress("C:/Users/07979/Pictures/1.jpg");  // 附件的地址(相对地址、绝对地址都行)
            cell.setHyperlink(hyperlink);
        }
    }
}

Beim Exportieren von Excel müssen Sie diesen Prozessor registrieren:

ExcelUtil#()::

@Component
@Slf4j
public class ExcelUtil<T> {
    
    
	// ...

	public void simpleExcelWrite(String filePath, Class<T> clazz, List<T> dataList) {
    
    
        EasyExcel.write(filePath, clazz)
        		.registerWriteHandler(new PhotoHandler())
        		.sheet(SHEET_NAME).doWrite(dataList);
    }
}

veranschaulichen:

  1. Es können mehrere Bearbeiter registriert werden. wie:
EasyExcel.write(filePath, clazz)
        		.registerWriteHandler(new PhotoHandler())
        		.registerWriteHandler(new PhotoHandler2())
        		.sheet(SHEET_NAME).doWrite(dataList);

Nachdem Sie den Code ausgeführt haben:
Fügen Sie hier eine Bildbeschreibung ein
Klicken Sie mit der Maus auf die Überschrift der ersten Spalte, um zu springen.

Fügen Sie hier eine Bildbeschreibung ein
Sie können auch springen, indem Sie mit der Maus auf die Spalte „Foto“ klicken.

=============================================== =======================================
2023-01-09 Update:

EasyExcel exportiert Excel, um das Zelltextformat festzulegen: EasyExcel exportiert Excel, um das Zelltextformat festzulegen (gültig im persönlichen Test)

Nur gültig für Zeilen mit Daten:

Methode 1:

@ExcelProperty(value = "创建时间")
@ContentStyle(horizontalAlignment = HorizontalAlignmentEnum.LEFT, dataFormat = 49)
private String createTime;

Methode 2:

public class ExcelCellWriteHandler implements CellWriteHandler {
    
    

    @Override
    public void afterCellDispose(CellWriteHandlerContext context) {
    
    
        // 3.0 设置单元格为文本
        WriteCellData<?> cellData = context.getFirstCellData();
        WriteCellStyle writeCellStyle = cellData.getOrCreateStyle();
        DataFormatData dataFormatData = new DataFormatData();
        dataFormatData.setIndex((short) 49);
        writeCellStyle.setDataFormatData(dataFormatData);
    }

    @Override
    public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, List<WriteCellData<?>> cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {
    
    
        // 3.0 设置单元格为文本
        Workbook workbook = writeSheetHolder.getSheet().getWorkbook();
        DataFormat dataFormat = workbook.createDataFormat();
        for (WriteCellData<?> writeCellData : cellDataList) {
    
    
            WriteCellStyle writeCellStyle = writeCellData.getOrCreateStyle();
            DataFormatData dataFormatData = new DataFormatData();
            dataFormatData.setIndex(dataFormat.getFormat("@"));
            writeCellStyle.setDataFormatData(dataFormatData);
        }
    }

}

public static <T> void simpleExcelWrite(String filePath, Class<?> clazz, List<T> dataList, String sheetName) {
    
    
    EasyExcel.write(filePath, clazz).sheet(sheetName).registerWriteHandler(new ExcelCellWriteHandler()).doWrite(dataList);
}

Je suppose que tu aimes

Origine blog.csdn.net/sco5282/article/details/121303881
conseillé
Classement