1. 程式人生 > >jxls中jxlsHelper無法刪除模板問題

jxls中jxlsHelper無法刪除模板問題

/這是zos的輸出流
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ZipOutputStream zos = new ZipOutputStream(bos);
          //迴圈
            for (xxx:xxxxx) {
                 //****業務程式碼
                //定義檔案的輸入流
                InputStream input = EnvUtils.isDevFromSystem() ?
                        this.getClass().getClassLoader().getResourceAsStream(
                                WmsConstant.WMS_TEMPLATE_ROOT + filename) :
                        new
FileInputStream(WmsPathUtil.getTemplateReportPath().resolve(filename).toFile()); //定義檔案的輸出流,但是這是作為zip流的一部分 ByteArrayOutputStream output = new ByteArrayOutputStream(); //用jxlsHelper來處理xlxs輸出了流 JxlsHelper jxlsHelper = new WmsJxlsHelper(); jxlsHelper.processTemplate(input, output, context); //命名檔案
zos.putNextEntry(new ZipEntry(channelName + ".xlsx")); //把xlxs輸出流作為輸入流輸入到zip輸出流中 zos.write(output.toByteArray()); zos.closeEntry(); output.close(); } //關閉zos,但是outputStream流依然存在記憶體中 zos.close
(); return genResponseEntityFromBytes(MediaType.APPLICATION_OCTET_STREAM, downloadFileName, bos.toByteArray());

問題:excel生成時template不能刪除,在查詢jxlsHelper#processTemplate 官方文當的過程中有api

    jxlsHelper.setDeleteTemplateSheet(isDeleteTemplateSheet);
    jxlsHelper.setHideTemplateSheet(isDeleteTemplateSheet);

然而,設定後根本就沒啥用。 參考原始碼:

        //呼叫的api
   public JxlsHelper processTemplate(InputStream templateStream, OutputStream targetStream, Context context) throws IOException {
        Transformer transformer = this.createTransformer(templateStream, targetStream);
        this.processTemplate(context, transformer);
        return this;
    }

//實際執行的api函式
public void processTemplate(Context context, Transformer transformer) throws IOException {
        this.areaBuilder.setTransformer(transformer);
        List<Area> xlsAreaList = this.areaBuilder.build();
        Iterator var4 = xlsAreaList.iterator();

        Area xlsArea;
        while(var4.hasNext()) {
            xlsArea = (Area)var4.next();
            xlsArea.applyAt(new CellRef(xlsArea.getStartCellRef().getCellName()), context);
        }

        if (this.processFormulas) {
            var4 = xlsAreaList.iterator();

            while(var4.hasNext()) {
                xlsArea = (Area)var4.next();
                this.setFormulaProcessor(xlsArea);
                xlsArea.processFormulas();
            }
        }
        //輸出了excel,有刪除嗎?有用到deleteTemplateSheet或者hideTemplateSheet引數嗎?沒有!
        transformer.write();
    }
public class CusJxlsHelper extends JxlsHelper {
    private static Logger logger = LoggerFactory.getLogger(WmsJxlsHelper.class);

    public static WmsJxlsHelper instance() {
        return new WmsJxlsHelper();
    }
    //重寫了processTemplate這個方法
    @Override
    public void processTemplate(Context context, Transformer transformer) throws IOException {
        AreaBuilder areaBuilder = this.getAreaBuilder();
        boolean processFormulas = this.isProcessFormulas();

        areaBuilder.setTransformer(transformer);
        List<Area> xlsAreaList = areaBuilder.build();
        Iterator var4 = xlsAreaList.iterator();

        Area xlsArea;
        while (var4.hasNext()) {
            xlsArea = (Area) var4.next();
            xlsArea.applyAt(new CellRef(xlsArea.getStartCellRef().getCellName()), context);
        }

        if (processFormulas) {
            var4 = xlsAreaList.iterator();

            while (var4.hasNext()) {
                xlsArea = (Area) var4.next();
                this.setFormulaProcessor(xlsArea);
                xlsArea.processFormulas();
            }
        }
        //增加了刪除template sheet的業務控制
        logger.info("===================delete template sheet in WmsJxlsHelper");
        if (this.isDeleteTemplateSheet()) {
            transformer.deleteSheet("TEMPLATE");
        }

        transformer.write();
    }

//這裡不想寫的,但是不寫會報錯
    private Area setFormulaProcessor(Area xlsArea) {
        FormulaProcessor fp = this.getFormulaProcessor();
        if (fp == null) {
            if (this.isUseFastFormulaProcessor()) {
                fp = new FastFormulaProcessor();
            } else {
                fp = new StandardFormulaProcessor();
            }
        }

        xlsArea.setFormulaProcessor((FormulaProcessor) fp);
        return xlsArea;
    }
}

最後把官方的jxlsHelper更換為自定義的CusJxlsHelper,ok,工作正常。 最終程式碼如下:

 @RequestMapping(value = WmsUrlConstants.Shipment.RED_DOWNLOAD_SHIPPING_DATA_LIST, method = RequestMethod.GET)
    public ResponseEntity<byte[]> downloadShippingDataList(@PathVariable("shipmentId") @NotNull Long shipmentId) {
        String filename = "xxxxxxx.xlsx";
        try {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
            int listCount = shipmentDownloadService.getShippingDataCountByred(shipmentId);
            ComStoreModel store = ComStore.getStoreById(getSelStoreId());
            String downloadFileName = WmsConstant.ShippingDataList.FILE_NAME + store.getStoreName()
                    + "_ShippingData_" + sdf.format(new Date()) + "-" + listCount + "件.zip";
            List<ShipmentDisShippingDataListBean> shippingDataList =
                    shipmentDownloadService.getShippingDataListBeans(shipmentId);
            ExcelZipBuilder zipBuilder = new ExcelZipBuilder();
            //獲取模板檔案
            Path defaultFile = EnvUtils.isDevFromSystem() ?
                    Paths.get(Objects.requireNonNull(this.getClass().getClassLoader().getResource(
                            WmsConstant.WMS_TEMPLATE_ROOT + filename)).getPath().replaceFirst("^/(.:/)", "$1")) :
                    WmsPathUtil.getTemplateReportPath().resolve(filename);

            for (xxxxx x : xxxxxxxList) {
                Context context = new Context();
                //業務程式碼
                zipBuilder.addEntry(context, defaultFile.toFile(), channelName + ".xlsx");
            }
            byte[] result = zipBuilder.build();
            return genResponseEntityFromBytes(MediaType.APPLICATION_OCTET_STREAM,
                    downloadFileName, result);
        } catch (Exception e) {
            throw new CodeException(CodeConstant.Common.DOWNLOAD_FILE_ERROR, e);
        }
    }

ExcelZipBuilder 程式碼如下

package com.voyageone.ecerp.web.wms.helper;

import org.jxls.common.Context;
import org.jxls.util.JxlsHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * Created with IntelliJ IDEA.
 *
 * @author: jet.xie
 * @Date: 2018/9/13
 * @Time: 15:19
 * @Description:
 * @version: 1.0.0
 */
public class ExcelZipBuilder {
    private static Logger logger = LoggerFactory.getLogger(WmsJxlsHelper.class);
    private List<Entry> entries = new ArrayList<>();

    public ExcelZipBuilder addEntry(Context context, File templateFile, String targetFileName) {
        entries.add(new Entry(context, targetFileName, templateFile, true));
        return this;
    }

    public ExcelZipBuilder addEntry(Context context, File templateFile, String targetFileName, boolean isDeleteTemplateSheet) {
        entries.add(new Entry(context, targetFileName, templateFile, isDeleteTemplateSheet));
        return this;
    }

    public byte[] build() throws IOException {
        try (ByteArrayOutputStream bos = new ByteArrayOutputStream();
             ZipOutputStream zos = new ZipOutputStream(bos)
        ) {
            logger.info("====================壓縮{}份檔案", entries.size());
            for (Entry entry : entries) {
                ZipEntry zipEntry = new ZipEntry(entry.entryName);
                zos.putNextEntry(zipEntry);
                byte[] bytes = entry.toByte();
                zos.write(bytes);
                zos.closeEntry();
            }
            zos.close();
            return bos.toByteArray();
        }
    }

    private static class Entry {
        /**
         * 填充內容
         */
        private Context context;
        /**
         * excel檔名稱
         */
        private String entryName;
        /**
         * 模板名稱
         */
        private File templateFile;

        /**
         * 是否刪除templateSheet
         */
        private boolean isDeleteTemplateSheet;

        Entry(Context context, String entryName, File templateFile, boolean isDeleteTemplateSheet) {
            this.context = context;
            this.entryName = entryName;
            this.templateFile = templateFile;
            this.isDeleteTemplateSheet = isDeleteTemplateSheet;
        }

        byte[] toByte() throws IOException {
            //讀取檔案流
            FileInputStream input = new FileInputStream(templateFile);
            ByteArrayOutputStream output = new ByteArrayOutputStream();
            //用jxlsHelper來處理xlxs輸出了流
            JxlsHelper jxlsHelper = new WmsJxlsHelper();
            jxlsHelper.setDeleteTemplateSheet(isDeleteTemplateSheet);
            jxlsHelper.processTemplate(input, output, context);
            return output.toByteArray();
        }

        public boolean isDeleteTemplateSheet() {
            return isDeleteTemplateSheet;
        }

        public void setDeleteTemplateSheet(boolean deleteTemplateSheet) {
            isDeleteTemplateSheet = deleteTemplateSheet;
        }
    }

}