最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Spring?boot?easyexcel?實(shí)現(xiàn)復(fù)合數(shù)據(jù)導(dǎo)出、按模塊導(dǎo)出功能

 更新時間:2023年09月20日 10:30:42   作者:何xiao樹  
這篇文章主要介紹了Spring?boot?easyexcel?實(shí)現(xiàn)復(fù)合數(shù)據(jù)導(dǎo)出、按模塊導(dǎo)出,實(shí)現(xiàn)思路流程是準(zhǔn)備一個導(dǎo)出基礎(chǔ)填充模板,默認(rèn)填充key,本文給大家介紹的非常詳細(xì),需要的朋友可以參考下

場景:

導(dǎo)出數(shù)據(jù)為1對多的復(fù)合數(shù)據(jù)
一個模塊是一條數(shù)據(jù),直接填充數(shù)據(jù)無法實(shí)現(xiàn)

如圖:

紅框內(nèi)為一條數(shù)據(jù)(1對多),下方箭頭指向?yàn)榈诙l數(shù)據(jù)
如果直接填充,只能填充第一條,第二條就沒辦法了。
由于多行都包含許多,固定表頭,只能走填充路線,怎么實(shí)現(xiàn)呢

在這里插入圖片描述

實(shí)現(xiàn)思路流程:

準(zhǔn)備一個導(dǎo)出基礎(chǔ)填充模板,默認(rèn)填充key

在這里插入圖片描述

計(jì)算,復(fù)制起始行、復(fù)制結(jié)束行、復(fù)制行數(shù);用poi的 復(fù)制行方式生成新模塊,也就是一條新的 1對多數(shù)據(jù)。 sheet.copyRows(startRows.get(i), endRows.get(i), copyStartRows.get(i), policy);

在這里插入圖片描述

復(fù)制后

在這里插入圖片描述

根據(jù)填充fillKey 規(guī)律,生成填充key集合;然后進(jìn)行填充key替換

在這里插入圖片描述

并返回待填充的 fillKeys ,與數(shù)據(jù)對齊,進(jìn)行數(shù)據(jù)填充。

如果數(shù)據(jù)過大,經(jīng)測試一般一個 sheet 最好 100個復(fù)合數(shù)據(jù),多的再進(jìn)行 sheet復(fù)制 xssfWorkbook.cloneSheet(0,"sheet" + (i+1));

參考代碼:

    @ApiOperation(value = "數(shù)據(jù)-excel導(dǎo)出",notes = "首次調(diào)用會返回一個processId標(biāo)識,查詢進(jìn)度攜帶標(biāo)識")
    @GetMapping("/export")
    public ResultData exportHtMeta(String processId){
        HtMetaExcelProcessVo htMetaExcelProcessVo;
        if (!StringUtils.hasLength(processId)){
            try {
                htMetaExcelProcessVo=htMetaInfoService.exportHtMetaCopyModule(processId);
            } catch (Exception e) {
                throw new ExcelHandlerException("導(dǎo)入失敗:"+e.getMessage());
            }
        }else {
            Cache cache = cacheManager.getCache(HtMetaConstants.EXPORT_PREFIX);
            htMetaExcelProcessVo=cache.get(processId,HtMetaExcelProcessVo.class);
            if (htMetaExcelProcessVo==null){
                return new ResultData(ErrorCodeEnum.NOT_FOUND_DATA.getCode(),"該導(dǎo)入uid,沒有對應(yīng)數(shù)據(jù)");
            }
            if (htMetaExcelProcessVo.getCurProcess().equals(htMetaExcelProcessVo.getTotalProcess())){
                htMetaExcelProcessVo.setImportStatus(HtMetaConstants.EXCEL_PROCESS_SUCCESS);
                htMetaExcelProcessVo.setMsg("導(dǎo)出成功");
            }
        }
        return new ResultData(htMetaExcelProcessVo);
    }
/**
     * 導(dǎo)出批次大小,每個sheet導(dǎo)出模塊大小
     */
    private static final Integer SPLIT_SIZE=100;
    @Override
    public HtMetaExcelProcessVo exportHtMetaCopyModule(String exportKey) throws Exception{
        HtMetaExcelProcessVo excelProcessVo;
        Cache cache = cacheManager.getCache(HtMetaConstants.EXPORT_PREFIX);
        if (cache==null){
            throw new ExcelHandlerException("ehcahe 緩存配置異常");
        }
        if (StringUtils.hasLength(exportKey)){
            //檢查是否存在已導(dǎo)出
            if (cache.get(exportKey)!=null){
                return cache.get(exportKey,HtMetaExcelProcessVo.class);
            }
        }else {
            exportKey = UUID.randomUUID().toString().replace("-", "");
        }
        ClassPathResource resource = new ClassPathResource("excel-template/導(dǎo)入模板.xlsx");
        String exportPath = new File("").getAbsolutePath() + File.separator + "ht-meta-export";
        if (!new File(exportPath).exists()){
            boolean mkdir = new File(exportPath).mkdir();
            log.info("導(dǎo)出目錄創(chuàng)建:{}",mkdir);
        }
        File exportFile = new File(exportPath+File.separator+exportKey+".xlsx");
        log.info("華泰-元數(shù)據(jù),導(dǎo)出文件:{}",exportFile.getAbsolutePath());
        //按數(shù)據(jù)生成-臨時導(dǎo)入模板
        File tmpExportTemplate = null;
        ExcelWriter excelWriter =null;
        try {
            tmpExportTemplate = File.createTempFile("temp", ".xlsx");
            List<HtMetaClusterInfoVo> list = htMetaClusterInfoMapper.clusterList(new HtMetaClusterQo());
            log.info("導(dǎo)出數(shù)據(jù)條數(shù):{}",list.size());
            int sheetSize = (list.size() / SPLIT_SIZE);
            if (sheetSize==1){
                excelProcessVo = new HtMetaExcelProcessVo(HtMetaConstants.EXCEL_PROCESS_ING, 0, 4, "正在導(dǎo)出");
            }else {
                excelProcessVo = new HtMetaExcelProcessVo(HtMetaConstants.EXCEL_PROCESS_ING, 0, 4+sheetSize, "正在導(dǎo)出");
            }
            excelProcessVo.setProcessId(exportKey);
            cache.put(exportKey,excelProcessVo);
            //階段1
            refreshProcess(cache,exportKey);
            //單條導(dǎo)出
            if (list.size()==1){
                FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build();
                excelWriter = EasyExcel.write(exportFile).withTemplate(resource.getInputStream()).build();
                WriteSheet writeSheet = EasyExcel.writerSheet(0).build();
                HtMetaClusterInfoVo e = list.get(0);
                excelWriter.fill(new FillWrapper("data0", Collections.singletonList(e)), fillConfig, writeSheet);
                List<HtMetaNodeInfoVo> nodeInfoVos = e.getNodeInfoVos();
                List<HtMetaBsInfoVo> bsInfoVos = e.getBsInfoVos();
                excelWriter.fill(new FillWrapper("data1", nodeInfoVos), fillConfig, writeSheet);
                excelWriter.fill(new FillWrapper("data2", bsInfoVos), fillConfig, writeSheet);
                excelWriter.finish();
                excelProcessVo = new HtMetaExcelProcessVo(HtMetaConstants.EXCEL_PROCESS_SUCCESS, 4, 4, "導(dǎo)出成功");
                excelProcessVo.setProcessId(exportKey);
                cache.put(exportKey,excelProcessVo);
                return excelProcessVo;
            }
            int overSize;
            if (sheetSize>1){
                //剩余數(shù)量
                overSize = list.size() - (sheetSize * SPLIT_SIZE);
                log.info("剩余數(shù)據(jù)條數(shù):{}",overSize);
            } else {
                overSize = 0;
            }
            log.info("開始生成數(shù)據(jù)導(dǎo)出模板");
            List<List<String>> fillKeys = HtMetaExcelUtil.copyMultiRow(6, 17,
                    12,list.size() - 1,
                    resource.getInputStream(), tmpExportTemplate);
            log.info("生成結(jié)束");
            //階段2
            refreshProcess(cache,exportKey);
            FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build();
            excelWriter = EasyExcel.write(exportFile).withTemplate(tmpExportTemplate).build();
            //階段3
            refreshProcess(cache,exportKey);
            String finalExportKey = exportKey;
            ExcelWriter finalExcelWriter = excelWriter;
            File finalTmpExportTemplate = tmpExportTemplate;
            CompletableFuture.runAsync(()->{
                try {
                    fiilTemplateExcel(finalExportKey, cache, finalExcelWriter, list, sheetSize, overSize, fillKeys, fillConfig);
                    log.info("填充結(jié)束");
                }finally {
                    if (finalExcelWriter!=null){
                        finalExcelWriter.finish();
                    }
                    boolean delete = finalTmpExportTemplate.delete();
                    log.info("臨時導(dǎo)入模板刪除: {}",delete);
                }
            });
        } catch (IOException e) {
            log.info("導(dǎo)出失敗");
            throw e;
        }
        return excelProcessVo;
    }

HtMetaExcelUtil

import lombok.extern.slf4j.Slf4j;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.tomcat.util.http.fileupload.IOUtils;
import org.springframework.util.StringUtils;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.nio.file.Files;
import java.util.Arrays;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
/**
 * @author xiaoshu
 * @description
 * @date 2023年09月01日 23:34
 */
@Slf4j
public class HtMetaExcelUtil {
    /**
     * 導(dǎo)出批次大小,每個sheet導(dǎo)出模塊大小
     */
    private static final Integer SPLIT_SIZE=100;
    /**
     * poi對excel進(jìn)行 多行模塊復(fù)制,并替換 Fill填充前綴
     *
     * @param startRowIndex    模塊-起始行index,excel標(biāo)記行號-1
     * @param endRowIndex      模塊-結(jié)束行
     * @param moduleRowSize    模塊行數(shù)
     * @param copyCount        復(fù)制次數(shù)
     * @param sourceFileStream 源文件流
     * @param outFile          輸出文件
     * @return List<List<String>> 填充fillKey列表
     */
    public static List<List<String>> copyMultiRow(int startRowIndex, int endRowIndex,
                                             int moduleRowSize, int copyCount,
                                             InputStream sourceFileStream,
                                             File outFile
    ) {
        File tempFile =null;
        int sheetSize=0;
        if (copyCount>SPLIT_SIZE){
            sheetSize= (copyCount + 1) / SPLIT_SIZE;
            log.info("復(fù)制sheet數(shù)量:{}",sheetSize);
            copyCount=SPLIT_SIZE-1;
        }
        //填充key列表
        List<List<String>> fillKeys = new LinkedList<>();
        //添加填充模板,默認(rèn)key
        fillKeys.add(Arrays.asList("data0","data0","data1","data2"));
        //復(fù)制起始行
        int startRow = startRowIndex;
        //復(fù)制結(jié)束行
        int endRow = endRowIndex;
        //目標(biāo)起始行
        int targetRow = endRow + 1;
        List<Integer> startRows = new LinkedList<>();
        startRows.add(startRow);
        List<Integer> endRows = new LinkedList<>();
        endRows.add(endRow);
        List<Integer> copyStartRows = new LinkedList<>();
        copyStartRows.add(targetRow);
        XSSFWorkbook workbook = null;
        XSSFWorkbook xssfWorkbook = null;
        try {
            workbook = new XSSFWorkbook(sourceFileStream);
            for (int i = 1; i < copyCount; i++) {
                startRow = startRow + moduleRowSize;
                startRows.add(startRow);
                endRow = endRow + moduleRowSize;
                endRows.add(endRow);
                targetRow = endRow + 1;
                copyStartRows.add(targetRow);
            }
            XSSFSheet sheet = workbook.getSheetAt(0);
            CellCopyPolicy policy = new CellCopyPolicy();
            policy.setCopyCellFormula(false);
            policy.setMergeHyperlink(false);
            policy.setMergeHyperlink(false);
            for (int i = 0; i < copyCount; i++) {
                sheet.copyRows(startRows.get(i), endRows.get(i), copyStartRows.get(i), policy);
                setRowsBorder(workbook,sheet,copyStartRows.get(i)+5,copyStartRows.get(i)+7);
                setRowsBorder(workbook,sheet,copyStartRows.get(i)+9,copyStartRows.get(i)+12);
            }
            //生成臨時模板文件
            tempFile = File.createTempFile("temp", ".xlsx");
            //寫入復(fù)制模塊后的文件
            workbook.write(Files.newOutputStream(tempFile.toPath()));
            //移除模板本身索引
            startRows.remove(0);
            //添加最后一列索引
            if (copyCount!=1){
                Integer lastRow = startRows.get(startRows.size() - 1);
                startRows.add(lastRow + moduleRowSize);
            }
            //替換填充前綴
            xssfWorkbook = new XSSFWorkbook(tempFile);
            XSSFSheet xssfSheet = xssfWorkbook.getSheetAt(0);
            int initIndex = 3;
            if (copyCount!=1){
                for (Integer row : startRows) {
                    //每行對應(yīng)填充key
                    List<String> fillKey = new LinkedList<>();
                    XSSFRow row1 = xssfSheet.getRow(row);
                    replaceRowValue(row1, "data0", "data" + initIndex);
                    fillKey.add("data" + initIndex);
                    XSSFRow row2 = xssfSheet.getRow(row + 2);
                    replaceRowValue(row2, "data0", "data" + initIndex);
                    fillKey.add("data" + initIndex);
                    XSSFRow row3 = xssfSheet.getRow(row + 4);
                    replaceRowValue(row3, "data1", "data" + (initIndex + 1));
                    fillKey.add("data" + (initIndex + 1));
                    XSSFRow row4 = xssfSheet.getRow(row + 8);
                    replaceRowValue(row4, "data2", "data" + (initIndex + 2));
                    fillKey.add("data" + (initIndex + 2));
                    initIndex = initIndex + 3;
                    fillKeys.add(fillKey);
                }
            }else {
                //每行對應(yīng)填充key
                List<String> fillKey = new LinkedList<>();
                int row=endRowIndex+1;
                XSSFRow row1 = xssfSheet.getRow(row);
                replaceRowValue(row1, "data0", "data" + initIndex);
                fillKey.add("data" + initIndex);
                XSSFRow row2 = xssfSheet.getRow(row + 2);
                replaceRowValue(row2, "data0", "data" + initIndex);
                fillKey.add("data" + initIndex);
                XSSFRow row3 = xssfSheet.getRow(row + 4);
                replaceRowValue(row3, "data1", "data" + (initIndex + 1));
                fillKey.add("data" + (initIndex + 1));
                XSSFRow row4 = xssfSheet.getRow(row + 8);
                replaceRowValue(row4, "data2", "data" + (initIndex + 2));
                fillKey.add("data" + (initIndex + 2));
                fillKeys.add(fillKey);
            }
            if (sheetSize>=1){
                for (int i = 0; i < sheetSize; i++) {
                    xssfWorkbook.cloneSheet(0,"sheet" + (i+1));
                }
            }
            //替換填充前綴->輸出文件
            xssfWorkbook.write(Files.newOutputStream(outFile.toPath()));
            return fillKeys;
        } catch (IOException | InvalidFormatException e) {
            throw new RuntimeException(e);
        } finally {
            try {
                if (xssfWorkbook != null) {
                    xssfWorkbook.close();
                }
                if (workbook != null) {
                    workbook.close();
                }
                if (sourceFileStream != null) {
                    sourceFileStream.close();
                }
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
            if (tempFile!=null){
                boolean delete = tempFile.delete();
                log.info("臨時模板刪除: {}",delete);
            }
        }
    }
    //添加邊框
    public static void setRowsBorder(XSSFWorkbook xssfWorkbook,XSSFSheet sheet
            ,int startRow,int endRow){
        // 創(chuàng)建單元格樣式
        XSSFCellStyle style = xssfWorkbook.createCellStyle();
        //上下左右邊框
        // 設(shè)置邊框樣式為實(shí)線
        style.setBorderTop(BorderStyle.THIN);
        style.setBorderBottom(BorderStyle.THIN);
        style.setBorderLeft(BorderStyle.THIN);
        style.setBorderRight(BorderStyle.THIN);
        // 設(shè)置邊框顏色為黑色
        style.setTopBorderColor(IndexedColors.BLACK.getIndex());
        style.setBottomBorderColor(IndexedColors.BLACK.getIndex());
        style.setLeftBorderColor(IndexedColors.BLACK.getIndex());
        style.setRightBorderColor(IndexedColors.BLACK.getIndex());
        for (int i = startRow; i < endRow; i++) {
            XSSFRow row = sheet.getRow(i);
            row.setRowStyle(style);
        }
    }
    /**
     * 行值替換
     * @param row      替換行
     * @param oldValue 過去值
     * @param newValue 替換值
     */
    public static void replaceRowValue(XSSFRow row, String oldValue, String newValue) {
        Iterator<Cell> cellIterator = row.cellIterator();
        cellIterator.forEachRemaining(e -> {
            if (StringUtils.hasLength(e.getStringCellValue())) {
                String cellValue = e.getStringCellValue();
                cellValue = cellValue.replace(oldValue, newValue);
                e.setCellValue(cellValue);
            }
        });
    }
    /**
     * 獲取導(dǎo)出文件
     * @param processId 進(jìn)度id
     * @return String - 文件路徑
     */
    public static String getHtExportFile(String processId) {
        File file = new File("");
        return  file.getAbsolutePath() + File.separator + "ht-meta-export" + File.separator + processId + ".xlsx";
    }
    /**
     * 瀏覽器文件下載
     * @param targetFile  目標(biāo)文件
     * @param response    response
     */
    public static void browserDownLoad(File targetFile, String downLoadName, HttpServletResponse response){
        OutputStream out = null;
        InputStream in = null;
        try {
            response.reset();
            response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(downLoadName, "UTF-8"));
            response.addHeader("Content-Length", "" + targetFile.length());
            response.setContentType("application/vnd.ms-excel");
            out = new BufferedOutputStream(response.getOutputStream());
            in = new BufferedInputStream(new FileInputStream(targetFile));
            IOUtils.copy(in, out);
            out.flush();
        } catch (Exception e) {
        } finally {
            IOUtils.closeQuietly(in);
            IOUtils.closeQuietly(out);
        }
    }
}

到此這篇關(guān)于Spring boot easyexcel 實(shí)現(xiàn)復(fù)合數(shù)據(jù)導(dǎo)出、按模塊導(dǎo)出的文章就介紹到這了,更多相關(guān)Spring boot easyexcel 復(fù)合數(shù)據(jù)導(dǎo)出內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 關(guān)于在Java中使用預(yù)定義類

    關(guān)于在Java中使用預(yù)定義類

    這篇文章主要介紹了關(guān)于在Java中使用預(yù)定義類,預(yù)定義類就是Java類庫(或第三方庫)中已經(jīng)定義好的類,例如,Math 類和 Date 類,需要的朋友可以參考下
    2023-05-05
  • SpringBoot整合RocketMQ的方法詳解

    SpringBoot整合RocketMQ的方法詳解

    這篇文章主要為大家詳細(xì)介紹了SpringBoot整合RocketMQ的方法,文中的示例代碼講解詳細(xì),對我們學(xué)習(xí)有一定幫助,感興趣的小伙伴可以了解一下
    2022-08-08
  • Java 數(shù)據(jù)結(jié)構(gòu)之時間復(fù)雜度與空間復(fù)雜度詳解

    Java 數(shù)據(jù)結(jié)構(gòu)之時間復(fù)雜度與空間復(fù)雜度詳解

    算法復(fù)雜度分為時間復(fù)雜度和空間復(fù)雜度。其作用: 時間復(fù)雜度是度量算法執(zhí)行的時間長短;而空間復(fù)雜度是度量算法所需存儲空間的大小
    2021-11-11
  • mybatis if傳入字符串?dāng)?shù)字踩坑記錄及解決

    mybatis if傳入字符串?dāng)?shù)字踩坑記錄及解決

    這篇文章主要介紹了mybatis if傳入字符串?dāng)?shù)字踩坑記錄及解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-02-02
  • SpringBoot整合Milvus的實(shí)現(xiàn)

    SpringBoot整合Milvus的實(shí)現(xiàn)

    本文主要介紹了SpringBoot整合Milvus的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-07-07
  • SpringMVC前后端參數(shù)映射

    SpringMVC前后端參數(shù)映射

    在web開發(fā)中我們都要進(jìn)行前端傳參后端取參的過程,本文主要介紹了SpringMVC前后端參數(shù)映射,針對GET,?POST,?PUT,?DELETE?請求的參數(shù)該如何映射,感興趣的可以了解一下
    2023-08-08
  • Java 中 Form表單數(shù)據(jù)的兩種提交方式

    Java 中 Form表單數(shù)據(jù)的兩種提交方式

    本文給大家分享java中form表單數(shù)據(jù)的兩種提交方式,分別是get從制定的服務(wù)器中獲取數(shù)據(jù),pos方式提交數(shù)據(jù)給指定的服務(wù)器處理,本文給大家介紹的非常詳細(xì),需要的朋友參考下吧
    2016-12-12
  • SpringBoot整合Jackson超詳細(xì)用法(附Jackson工具類)

    SpringBoot整合Jackson超詳細(xì)用法(附Jackson工具類)

    這篇文章主要介紹了SpringBoot整合Jackson超詳細(xì)教程,本篇講的是Jackson的詳細(xì)用法,Jackson工具類在文章最后,直接復(fù)制粘貼即可使用,需要的朋友可以參考下
    2023-03-03
  • SpringBoot+Redis布隆過濾器防惡意流量擊穿緩存

    SpringBoot+Redis布隆過濾器防惡意流量擊穿緩存

    本文主要介紹了SpringBoot+Redis布隆過濾器防惡意流量擊穿緩存,文中根據(jù)實(shí)例編碼詳細(xì)介紹的十分詳盡,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • java類加載機(jī)制、類加載器、自定義類加載器的案例

    java類加載機(jī)制、類加載器、自定義類加載器的案例

    這篇文章主要介紹了java類加載機(jī)制、類加載器、自定義類加載器的案例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-02-02

最新評論

白山市| 天水市| 永和县| 田林县| 彰化县| 江孜县| 宝应县| 彭水| 宝山区| 清流县| 青浦区| 长子县| 乌拉特前旗| 禄丰县| 恭城| 万载县| 平安县| 临湘市| 陆良县| 塘沽区| 宁化县| 五台县| 昌邑市| 凤庆县| 伊通| 顺义区| 云霄县| 龙山县| 新昌县| 宝山区| 措勤县| 和田市| 新巴尔虎左旗| 修文县| 申扎县| 贵德县| 竹山县| 达日县| 朔州市| 新沂市| 宝丰县|