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 EasyExcel
man Excel-Dateien über verwaltet.
Codierungsideen:
Excel-Import:
- Durchsuchen Sie den Ordner und wählen Sie die Excel-Datei aus, die hochgeladen werden soll. Verwenden Sie hier das POSTMAN-Tool.
- Lokale Dateien an den angegebenen Speicherort auf dem Server hochladen;
- Der Server analysiert die Excel-Datei.
- Speichern Sie die in Excel analysierten Daten in der Datenbank.
Excel-Export
- Abfragebedingungen festlegen;
- Fragen Sie die entsprechenden Daten in der Datenbank ab;
- Daten in Excel schreiben;
- 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:
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:
EasyExcel.read(filePath, clazz, excelListener).sheet().doRead();
RuftExcelListener
die Methode in der Klasse auf und speichert die gelesenen Daten indataList
der Sammlung.- Die Klasse hier
ExcelUtil
verwendet Generika. Sie können jede Art von Daten übergeben, die Sie importieren möchten. Was ich hier importiere, istExcelVo
Typ.
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:
- Eigenschaften in ExcelVo entsprechen Excel-Dateien
- 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:
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:
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
POM-Abhängigkeit ändern: geänderte easyexcel
Version. 2.0.0-beta2
Version 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:
- 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:
Klicken Sie mit der Maus auf die Überschrift der ersten Spalte, um zu springen.
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);
}