Java之POI導出Excel(二):多個sheet

来源:https://www.cnblogs.com/wyj-java/archive/2022/10/01/16747297.html
-Advertisement-
Play Games

相信在大部分的web項目中都會有導出導入Excel的需求,之前我也寫過一篇導出單個sheet工作表的文章,沒看過的小伙伴可以去看哈,鏈接也給大家放出來了:導出單個sheet 但是在我們日常的工作中,需求往往沒這麼簡單,可能需要將數據按類型分類導出或者數據量過大,需要分多張表導出等等。遇到類似的需求該 ...


相信在大部分的web項目中都會有導出導入Excel的需求,之前我也寫過一篇導出單個sheet工作表的文章,沒看過的小伙伴可以去看哈,鏈接也給大家放出來了:導出單個sheet

但是在我們日常的工作中,需求往往沒這麼簡單,可能需要將數據按類型分類導出或者數據量過大,需要分多張表導出等等。遇到類似的需求該怎麼辦呢,別慌,往下看。

一、pom引用

        pom文件中,添加以下依賴

查看代碼
        <!--Excel工具-->
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>5.2.2</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>5.2.2</version>
            <scope>compile</scope>
        </dependency>

二、工具類util

1.ExportSheetUtil

查看代碼
 package com.***.excel;
 
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.VerticalAlignment;
import org.springframework.http.MediaType;
 
import javax.servlet.http.HttpServletResponse;
import java.net.URLEncoder;
import java.util.List;
 
/**
 * @description: excel導出多個sheet工具類
 * @author: ***
 * @date: 2022/9/15
 */
public class ExportSheetUtil {
 
    /**
     * 拆解並導出多重Excel
     */
    public static void exportManySheetExcel(String fileName, List<ExcelSheet> mysheets, HttpServletResponse response) {
        //創建工作薄
        HSSFWorkbook wb = new HSSFWorkbook();
        //表頭樣式
        HSSFCellStyle style = wb.createCellStyle();
        // 垂直
        style.setVerticalAlignment(VerticalAlignment.CENTER);
        // 水平
        style.setAlignment(HorizontalAlignment.CENTER);
        //字體樣式
        HSSFFont fontStyle = wb.createFont();
        fontStyle.setFontName("微軟雅黑");
        fontStyle.setFontHeightInPoints((short) 12);
        style.setFont(fontStyle);
        for (ExcelSheet excel : mysheets) {
            //新建一個sheet
            //獲取該sheet名稱
            HSSFSheet sheet = wb.createSheet(excel.getFileName());
            //獲取sheet的標題名
            String[] handers = excel.getHanders();
            //第一個sheet的第一行為標題
            HSSFRow rowFirst = sheet.createRow(0);
            //寫標題
            for (int i = 0; i < handers.length; i++) {
                //獲取第一行的每個單元格
                HSSFCell cell = rowFirst.createCell(i);
                //往單元格裡寫數據
                cell.setCellValue(handers[i]);
                //加樣式
                cell.setCellStyle(style);
                //設置每列的列寬
                sheet.setColumnWidth(i, 4000);
            }
            //寫數據集
            List<String[]> dataset = excel.getDataset();
            for (int i = 0; i < dataset.size(); i++) {
                //獲取該對象
                String[] data = dataset.get(i);
                //創建數據行
                HSSFRow row = sheet.createRow(i + 1);
                for (int j = 0; j < data.length; j++) {
                    //設置對應單元格的值
                    row.createCell(j).setCellValue(data[j]);
                }
            }
        }
 
        // 下載文件谷歌文件名會亂碼,用IE
        try {
            response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName + ".xlsx", "utf-8"));
            response.setHeader("Cache-Control", "No-cache");
            response.flushBuffer();
            wb.write(response.getOutputStream());
            wb.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
 
}

2.ExcelSheet

查看代碼
 package com.***.excel;
 
import lombok.Data;
 
import java.util.List;
 
/**
 * @description: 導出多個sheet表
 * @author: ***
 * @date: 2022/9/15
 */
@Data
public class ExcelSheet {
 
    /*** sheet的名稱*/
    private String fileName;
 
    /*** sheet里的標題*/
    private String[] handers;
 
    /*** sheet里的數據集*/
    private List<String[]> dataset;
 
    public ExcelSheet(String fileName, String[] handers, List<String[]> dataset) {
        this.fileName = fileName;
        this.handers = handers;
        this.dataset = dataset;
    }
 
}

三、相關業務代碼

1.service層

    /*** 導出開票及運單信息*/
    ExportInvoiceAndBillVo exportInvoiceAndBillInfo(InvoiceReviewListDto dto);

2.impl實現類

        實現類里的代碼,需要各位根據自己的業務場景進行改動,無非就是將需要導出的數據先查出來,帶入模板中,調用工具類的方法導出。

查看代碼
 package com.***.vo.invoicereview;
 
import lombok.Data;
 
import java.io.Serializable;
import java.util.List;
 
/**
 * @description: 導出開票和運單信息Vo
 * @author: ***
 * @date: 2022/9/19
 */
@Data
public class ExportInvoiceAndBillVo implements Serializable {
 
    /*** 開票信息*/
    private List<String[]> invoiceList;
 
    /*** 運單信息*/
    private List<String[]> billList;
 
}
查看代碼
     @Override
    public ExportInvoiceAndBillVo exportInvoiceAndBillInfo(InvoiceReviewListDto dto) {
        ExportInvoiceAndBillVo invoiceAndBill = new ExportInvoiceAndBillVo();
        // 查詢需要導出的開票信息
        PageInfo<InvoiceReviewListVo> pageInfo = queryInvoiceReviewList(dto);
        List<InvoiceReviewListVo> invoiceList = pageInfo.getList();
        if (invoiceList.size() > 10000) {
            throw new ServiceException("開票數據過多,請分批次導出");
        }
        // 查詢需要導出的車運運單信息
        List<Long> invoiceIdList = invoiceList.stream().map(InvoiceReviewListVo::getInvoiceId).collect(Collectors.toList());
        List<ExportBillVo> billList = getBillInfo(invoiceIdList);
        if (billList.size() > 10000) {
            throw new ServiceException("運單數據過多,請分批次導出");
        }
        // 將表1 表2的數據 放入定義的對象Vo中
        invoiceAndBill.setInvoiceList(getInvoiceDataList(invoiceList));
        invoiceAndBill.setBillList(getBillDataList(billList));
        return invoiceAndBill;
    }

3.controller層

        controller層的代碼需要註意的是:

1.因為導出Excel一般都是通過瀏覽器進行下載的,所以入參中需要加入HttpServletResponse

2.調用封裝的工具類ExportSheetUtil中的exportManySheetExcel方法就可以了

3.表頭和表名需要各位根據自身的業務場景修改哈

查看代碼
     /**
     * 導出開票和運單信息
     */
    @Log
    @PostMapping("/exportInvoiceAndBillInfo")
    public void exportInvoiceAndBillInfo(@RequestBody InvoiceReviewListDto dto, HttpServletResponse response) {
        ExportInvoiceAndBillVo invoiceAndBillVo = invoiceFacadeService.exportInvoiceAndBillInfo(dto);
        //設置sheet的表頭與表名
        String[] invoiceSheetHead = {"開票編號", "票號", "公司名稱", "收票方名稱", "結算類型", "納稅識別碼", "收票聯繫人", "聯繫人電話", "運單總金額(元)", "含稅總金額(元)", "開票狀態", "提交開票時間", "運營審核時間", "運營審核人", "財務審核時間", "財務審核人", "開票完成時間", "沖銷操作人", "沖銷時間"};
        String[] billSheetHead = {"開票編號", "運單號", "發貨地", "收貨地", "司機", "司機電話", "貨物名稱", "貨物數量", "單位", "貨物重量(噸)", "運單狀態", "運單金額(元)", "含稅金額(元)"};
        ExcelSheet invoiceExcel = new ExcelSheet("開票信息", invoiceSheetHead, invoiceAndBillVo.getInvoiceList());
        ExcelSheet billExcel = new ExcelSheet("運單信息", billSheetHead, invoiceAndBillVo.getBillList());
        List<ExcelSheet> mysheet = new ArrayList<>();
        mysheet.add(invoiceExcel);
        mysheet.add(billExcel);
        ExportSheetUtil.exportManySheetExcel("開票及運單信息", mysheet, response);
    }

最終導出的Excel文件:


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 一、Spring Cloud Stream 在實際的企業開發中,消息中間件是至關重要的組件之一。消息中間件主要解決應用解耦,非同步消息,流量削鋒等問題,實現高性能,高可用,可伸縮和最終一致性架構。不同的中間件其實現方式,內部結構是不一樣的。如常見的RabbitMQ和Kafka,由於這兩個消息中間件的架 ...
  • 技術傳播的價值,不僅僅體現在通過商業化產品和開源項目來縮短我們構建應用的路徑,加速業務的上線速率,也體現在優秀工程師在工作效率提升、產品性能優化和用戶體驗改善等經驗方面的分享,以提高我們的專業能力。本文作者阿裡巴巴技術專家三畫,分享了自己和團隊在畫好架構圖方面的理念和經驗,首發於阿裡內部技術分享平臺... ...
  • 一、引言:什麼是 JSON JSON (Java Script Object Notation) 是一種很常用的數據格式,它常常用在 web 應用程式中。它可以表示結構化的數據。 下麵是常見的 JSON 文件結構 { "name": "Kamishiro Rize", "age": "22", "o ...
  • 如何工作 在某些 Java 虛擬機中,堆的實現截然不同:它更像一個傳送帶,每分配一個新對象,它就向前移動一格。 這意味著對象存儲空間的分配速度特別快。Java 的"堆指針"只是簡單地移動到尚未分配的區域,所以它的效率與 C++ 在棧上分配空間的效率相當 垃圾回收器工作時,一邊回收記憶體,一邊使堆中的對 ...
  • Java基礎之運算符 1.1 運算符介紹 1.1.1 運算符介紹 運算符是一種特殊的符號,用以表示數據的運算、賦值和比較等,運算符可分為: 1)算術運算符 2)賦值運算符 3)關係運算符 [比較運算符] 4)邏輯運算符 5)位運算符 [需要二進位] 6)三元運算符 1.2 算術運算符 1.2.1 介 ...
  • 數據描述與分析 在進行數據分析之前,我們需要做的事情是對數據有初步的瞭解,這個瞭解就涉及對行業的瞭解和對數據本身的敏感程度,通俗來說就是對數據的分佈有大概的理解,此時我們需要工具進行數據的描述,觀測數據的形狀等;而後才是對數據進行建模分析,挖掘數據中隱藏的位置信息。目前在數據描述和簡單分析方面做的比 ...
  • 2022-10-01 ALLOWED_HOSTS "ALLOWED_HOSTS"的含義: 它是指允許放在“ALLOWED_HOSTS”的主機進行訪問後端 “ALLOWED_HOSTS”的說明: 它一般預設是“127.0.0.1”,如果添加上其他的主機的話,其他主機也可訪問此項目的view,但是此時, ...
  • 2022-10-01 結果集的含義: 結果集就是在查詢過程中,返回的一個列表的集合。 常見的結果集在一些函數中查詢會返回,具體包括的函數有: filter、exclude、order_by 結果集的兩大特性: (1)惰性 指的是查詢時,如果不用則在mysql日誌中不會有查詢記錄。反之,如果使用(一般 ...
一周排行
    -Advertisement-
    Play Games
  • 概述:在C#中,++i和i++都是自增運算符,其中++i先增加值再返回,而i++先返回值再增加。應用場景根據需求選擇,首碼適合先增後用,尾碼適合先用後增。詳細示例提供清晰的代碼演示這兩者的操作時機和實際應用。 在C#中,++i 和 i++ 都是自增運算符,但它們在操作上有細微的差異,主要體現在操作的 ...
  • 上次發佈了:Taurus.MVC 性能壓力測試(ap 壓測 和 linux 下wrk 壓測):.NET Core 版本,今天計劃準備壓測一下 .NET 版本,來測試並記錄一下 Taurus.MVC 框架在 .NET 版本的性能,以便後續持續優化改進。 為了方便對比,本文章的電腦環境和測試思路,儘量和... ...
  • .NET WebAPI作為一種構建RESTful服務的強大工具,為開發者提供了便捷的方式來定義、處理HTTP請求並返迴響應。在設計API介面時,正確地接收和解析客戶端發送的數據至關重要。.NET WebAPI提供了一系列特性,如[FromRoute]、[FromQuery]和[FromBody],用 ...
  • 原因:我之所以想做這個項目,是因為在之前查找關於C#/WPF相關資料時,我發現講解圖像濾鏡的資源非常稀缺。此外,我註意到許多現有的開源庫主要基於CPU進行圖像渲染。這種方式在處理大量圖像時,會導致CPU的渲染負擔過重。因此,我將在下文中介紹如何通過GPU渲染來有效實現圖像的各種濾鏡效果。 生成的效果 ...
  • 引言 上一章我們介紹了在xUnit單元測試中用xUnit.DependencyInject來使用依賴註入,上一章我們的Sample.Repository倉儲層有一個批量註入的介面沒有做單元測試,今天用這個示例來演示一下如何用Bogus創建模擬數據 ,和 EFCore 的種子數據生成 Bogus 的優 ...
  • 一、前言 在自己的項目中,涉及到實時心率曲線的繪製,項目上的曲線繪製,一般很難找到能直接用的第三方庫,而且有些還是定製化的功能,所以還是自己繪製比較方便。很多人一聽到自己畫就害怕,感覺很難,今天就分享一個完整的實時心率數據繪製心率曲線圖的例子;之前的博客也分享給DrawingVisual繪製曲線的方 ...
  • 如果你在自定義的 Main 方法中直接使用 App 類並啟動應用程式,但發現 App.xaml 中定義的資源沒有被正確載入,那麼問題可能在於如何正確配置 App.xaml 與你的 App 類的交互。 確保 App.xaml 文件中的 x:Class 屬性正確指向你的 App 類。這樣,當你創建 Ap ...
  • 一:背景 1. 講故事 上個月有個朋友在微信上找到我,說他們的軟體在客戶那邊隔幾天就要崩潰一次,一直都沒有找到原因,讓我幫忙看下怎麼回事,確實工控類的軟體環境複雜難搞,朋友手上有一個崩潰的dump,剛好丟給我來分析一下。 二:WinDbg分析 1. 程式為什麼會崩潰 windbg 有一個厲害之處在於 ...
  • 前言 .NET生態中有許多依賴註入容器。在大多數情況下,微軟提供的內置容器在易用性和性能方面都非常優秀。外加ASP.NET Core預設使用內置容器,使用很方便。 但是筆者在使用中一直有一個頭疼的問題:服務工廠無法提供請求的服務類型相關的信息。這在一般情況下並沒有影響,但是內置容器支持註冊開放泛型服 ...
  • 一、前言 在項目開發過程中,DataGrid是經常使用到的一個數據展示控制項,而通常表格的最後一列是作為操作列存在,比如會有編輯、刪除等功能按鈕。但WPF的原始DataGrid中,預設只支持固定左側列,這跟大家習慣性操作列放最後不符,今天就來介紹一種簡單的方式實現固定右側列。(這裡的實現方式參考的大佬 ...