關於使用EasyExcle,進行數據導出后,文件無法打開,提示文件已損壞等一系列問題排查記錄

1. 排除掉編碼方面的問題,排查的重點是各個數據查詢語句是否有數據的存在,也就是說,查詢語句對應的數據庫表,是否有數據的存在,數據是否正常返回給到你的後端對象?如果!你需要輸出到excle文件中的數據,在數據庫表中並不存在,或者説你根本查不到數據,那麽如果你的代碼中存在對數據是否爲空的判斷的時候,你需要查看

excelWriter.write()方法是否沒有被調用,也就是它沒有往表中寫入數據。

2. 注意!一般情況下,沒有查到數據,不調用excelWriter.write()方法進行寫入似乎是合理的邏輯,但是可能是EasyExcle本身的bug,在不寫入數據的時候EXCLE文件默認你的文件是不完整從而導致失敗。

3. 解決的方法可以使用模板範文,填入固定提示文字數據,如(代碼僅供參考,需要結合自己代碼進行相應實現)

if (CollectionUtils.isNotEmpty(students)) {
        // 查詢數據不爲空,執行方法體(具體自己代碼實現)
    }
} else {
    // 查詢數據爲空,進行模板數據填入,避免文件損壞,無法打開
    List<List<Object>> rows = new ArrayList<>();
    List<Object> row = new ArrayList<>();
    for (int i = 0; i < heads.size(); i++) {
        row.add("暫無數據");
    }
    rows.add(row);
    excelWriter.write(rows, writeSheet);
}

代碼不唯一,最重要是能結合業務場景解決問題即可

--------------------------------------------------  分界綫   ------------------------------------------------------------------

2024.4.22 文檔補充:

提取了公用的代碼,編輯了一個比較通用的工具類,代碼如下(僅供參考哦):

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;

import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * EasyExcel自定義工具類
 */
public class EasyExcelUtils {

    /**
     * 创建一个Excel文件并写入数据。
     *
     * @param outputStream  输出流,通常从HttpServletResponse获取
     * @param sheetName     工作表名称
     * @param headTitle     头部标题
     * @param noDataMessage 无数据时显示的消息
     */
    public static void writeExcelWithNoData(OutputStream outputStream, String headTitle, String sheetName, String noDataMessage) {
        // 创建ExcelWriter
        // ExcelWriterBuilder writerBuilder = EasyExcel.write(outputStream); 最好不要用ExcelWriterBuilder,因爲發現用了這個導出來的文件也是破損的,不知道是不是easyexcle的每個版本都不同的原因,具體不得而知,博主用的是2.2.6
        // 至於outputStream,其實write還有一個入參是String pathName,傳的是路徑名,那麽使用输出流的方法其實则更加灵活,適合在於生成Excel并直接作为HTTP响应返回给客户端的時候使用,具體結合自己實際去更改
        ExcelWriter excelWriter = EasyExcel.write(outputStream).build();

        // 构建头部信息(應該會有人好奇爲什麽要List<List<String>> head 這樣定義這個List集合,其實看一下下面的head方法的源碼就知道了,源碼提供的head方法重載之後提供了兩個入參的方法,一個入參是List<List<String>> ,另一個是Class,
        // 當然我們也可以新建一個實體類來進行構建它的表頭信息,這也是最常用的方法,
        // 這裏單純是不想創建多一個實體類才用的List<List<String>> 這樣的形式)
        List<List<String>> head = new ArrayList<>();
        head.add(Arrays.asList(headTitle));

        // 构建工作表
        WriteSheet writeSheet = EasyExcel.writerSheet(sheetName).head(head).build();

        // 创建无数据时的行信息(統一的用於解釋原因的模板信息)
        List<List<Object>> rows = new ArrayList<>();
        List<Object> row = new ArrayList<>();
        row.add(noDataMessage);
        // 實際上rows就是一個二維列表,主要也是用來對應上述表頭格式的,否則數據填充的位置就對不准表頭了,所以不用把這裏想的太複雜,沒什麽太深奧的意義
        rows.add(row);

        // 写入数据到Excel
        excelWriter.write(rows, writeSheet);

        // 关闭writer,释放内存
        excelWriter.finish();
    }
}

注意事項,代碼注釋中也有提及,但還是單獨拿出來講講:

1.  List<List<String>> head 爲什麽要這樣子定義這個List集合?

答:在下圖中,head方法是有兩個不同的入參形式,其實我們這個形式就相當於在動態構建參數,而沒有借助對象來入參,所以,看下源碼就知道爲什麽要這樣定義這個集合了

2.  List<List<Object>> rows = new ArrayList<>();   List<Object> row = new ArrayList<>();  的定義

答:實際上就是在構建一個二維的列表,主要是用來對應上述表頭格式的位置的,不這麽寫數據填充的位置就對不准表頭了,所以不用把這裏想的太複雜,沒什麽太深奧的意義

3.  入參爲什麽會有一個 OutputStream outputStream?

答:同樣也可以從源碼來理解,write方法同樣也提供了兩個重載形式,實際上也可以使用

String pathName這種入參形式,但outputStream 這種使用输出流的方法其實则更加灵活,適合在於生成Excel并直接作为HTTP响应返回给客户端的時候使用,但是具體還是結合自己實際情況去更改即可

4.   outputStream 的值從哪裏獲取?

答: 實際上你在MVC的層面可以接收一個參數叫:HttpServletResponse response

outputStream 實際上就是等同於 response.getOutputStream()

寫到最後,一起看下調用的截圖和效果圖:

工具類的方法實際上就等同於注釋掉的代碼,效果是一樣的

//                ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream()).build();
//                List<List<String>> head = new ArrayList<>();
//                head.add(Arrays.asList("檢索結果"));
//                WriteSheet writeSheet = EasyExcel.writerSheet("學校數據").head(head).build();
//                List<List<Object>> rows = new ArrayList<>();
//                List<Object> row = new ArrayList<>();
//                row.add("在當前查詢條件下,暫無對應檢索數據");
//                rows.add(row);
//                excelWriter.write(rows,writeSheet);
//                excelWriter.finish();

                EasyExcelUtils.writeExcelWithNoData(response.getOutputStream(),"檢索結果","學校數據","在當前查詢條件下,暫無對應檢索數據");

下方是excle文件的效果圖,對代碼沒有太大概念的同學可以結合excle的效果來慢慢理解代碼:

  • 9
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
好的,您可以使用EasyExcel库来实现Java中Excel文件导出。 首先,您需要在您的项目中添加EasyExcel依赖。您可以在Maven中添加以下依赖: ```xml <dependency> <groupId>com.alibaba</groupId> <artifactId>easyexcel</artifactId> <version>2.2.11</version> </dependency> ``` 接下来,您需要编写Java代码来实现导出。 假设您有两个脚本页分别为Sheet1和Sheet2,您需要在导出文件中将这两个脚本页的数据都包含进去。 下面是一个示例代码,您可以根据您的需求来修改: ```java public void writeExcel() { // 创建ExcelWriter对象 String fileName = "example.xlsx"; ExcelWriter excelWriter = EasyExcel.write(fileName).build(); // 写入Sheet1数据 WriteSheet sheet1 = EasyExcel.writerSheet(0, "Sheet1").head(Sheet1Data.class).build(); List<Sheet1Data> sheet1DataList = getSheet1Data(); // 获取Sheet1数据 excelWriter.write(sheet1DataList, sheet1); // 写入Sheet2数据 WriteSheet sheet2 = EasyExcel.writerSheet(1, "Sheet2").head(Sheet2Data.class).build(); List<Sheet2Data> sheet2DataList = getSheet2Data(); // 获取Sheet2数据 excelWriter.write(sheet2DataList, sheet2); // 关闭ExcelWriter对象 excelWriter.finish(); } // 获取Sheet1数据 private List<Sheet1Data> getSheet1Data() { List<Sheet1Data> dataList = new ArrayList<>(); // TODO: 添加Sheet1数据 return dataList; } // 获取Sheet2数据 private List<Sheet2Data> getSheet2Data() { List<Sheet2Data> dataList = new ArrayList<>(); // TODO: 添加Sheet2数据 return dataList; } ``` 在上面的示例代码中,我们首先创建了一个ExcelWriter对象,然后分别写入了Sheet1和Sheet2的数据。您需要替换`Sheet1Data`和`Sheet2Data`为您自己的数据类,然后实现`getSheet1Data()`和`getSheet2Data()`方法来返回您的数据列表。 最后,我们调用`excelWriter.finish()`方法关闭ExcelWriter对象,完成Excel文件导出。 希望这个示例代码能够帮助您实现Excel文件导出

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值