java使用freemarker導出復雜的excel表格


正常導出excel表格使用的poi,但是導出復雜的excel有點困難,但是可以使用freemaker模板來導出復雜的excel。

  • 都是先生成一個Excel表格的模板,最好是增加一行數據。具體看圖里面的步驟。

  • 項目整體結構

  • 下面就直接看代碼

public class Data {
//代碼復制之后直接就可以運行了
    public static void main(String[] args) {
        demo();
    }

    public static void demo() {
        // 項目下的template路徑
        String path = new File("").getAbsolutePath() + "\\template";
        Map<String, Object> map = new HashMap<String, Object>();
        // 模板所在的路徑
        map.put("tempFoldPath", path);
        // 生成的路徑
        map.put("file", path + "/采購訂單.xls");
        // 模板名稱
        map.put("tampPath", "采購訂單.ftl");
        // 最后生成的表格的名稱
        map.put("excelName", "采購訂單-" + "Demo" + ".xls");
        // 封裝數據
        Map<String, Object> exlParam = new HashMap<>();
        exlParam.put("findList", new Data().list());
        // 調用方法,返回瀏覽器訪問的地址
        String downloadUrl = ExportExcelUtil.exportExcel(map, exlParam);
    }

    // 自己造假數據,正常來說都是從數據庫查詢出來拼裝數據的
    public List<Purbill> list() {
        List<Purbill> purbillList = new ArrayList<>();
        purbillList.add(new Purbill("1", "2", "名稱", "采購名稱", "規格參數", "參數指標", "場地", "10噸", 10, 20.2, 220.2, "品牌"));
        return purbillList;
    }

}

class Purbill {
    private String bidId;
    private String billno;
    private String categoryName;
    private String purname;
    private String specparams;
    private String paramnorm;
    private String productAddress;
    private String unit;
    private Integer nums;
    private Double price;
    private Double totalprice;
    private String brand;

    public Purbill(String bidId, String billno, String categoryName, String purname, String specparams,
            String paramnorm, String productAddress, String unit, Integer nums, Double price, Double totalprice,
            String brand) {
        super();
        this.bidId = bidId;
        this.billno = billno;
        this.categoryName = categoryName;
        this.purname = purname;
        this.specparams = specparams;
        this.paramnorm = paramnorm;
        this.productAddress = productAddress;
        this.unit = unit;
        this.nums = nums;
        this.price = price;
        this.totalprice = totalprice;
        this.brand = brand;
    }

    public String getBidId() {
        return bidId;
    }

    public void setBidId(String bidId) {
        this.bidId = bidId;
    }

    public String getBillno() {
        return billno;
    }

    public void setBillno(String billno) {
        this.billno = billno;
    }

    public String getCategoryName() {
        return categoryName;
    }

    public void setCategoryName(String categoryName) {
        this.categoryName = categoryName;
    }

    public String getPurname() {
        return purname;
    }

    public void setPurname(String purname) {
        this.purname = purname;
    }

    public String getSpecparams() {
        return specparams;
    }

    public void setSpecparams(String specparams) {
        this.specparams = specparams;
    }

    public String getParamnorm() {
        return paramnorm;
    }

    public void setParamnorm(String paramnorm) {
        this.paramnorm = paramnorm;
    }

    public String getProductAddress() {
        return productAddress;
    }

    public void setProductAddress(String productAddress) {
        this.productAddress = productAddress;
    }

    public String getUnit() {
        return unit;
    }

    public void setUnit(String unit) {
        this.unit = unit;
    }

    public Integer getNums() {
        return nums;
    }

    public void setNums(Integer nums) {
        this.nums = nums;
    }

    public Double getPrice() {
        return price;
    }

    public void setPrice(Double price) {
        this.price = price;
    }

    public Double getTotalprice() {
        return totalprice;
    }

    public void setTotalprice(Double totalprice) {
        this.totalprice = totalprice;
    }

    public String getBrand() {
        return brand;
    }

    public void setBrand(String brand) {
        this.brand = brand;
    }

}

主要是兩個map,一個map是封裝模板的位置和生成表格的位置,第二個map是封裝的數據。正常來說導出表格之后都是返回url請求的地址,這樣在真實項目中根據地址就可以下載出來了。

  • 下面是一個excel導出的一個工具類
public class ExportExcelUtil {

    public static String exportExcel(Map<String, Object> map, Map<String, Object> exlParam) {
        Template dateTmp = null;
        Writer fw = null;
        InputStream in = null;
        OutputStream out = null;
        try {
            // 此處需要給你個版本信息,Configuration cfg = new Configuration();這個方法已經過時了
            Configuration cfg = new Configuration(Configuration.VERSION_2_3_28);
            String tempFoldPath = (String) map.get("tempFoldPath"); // 模板所在的路徑
            String file = (String) map.get("file");// 生成表格模板的路徑
            String tampPath = (String) map.get("tampPath");// 模板名稱
            String excelName = (String) map.get("excelName");// 最后生成表格的名稱

            // **********初始化參數**********
            File tempFoldFile = new File(tempFoldPath);
            if (!tempFoldFile.exists()) {
                tempFoldFile.mkdirs();
            }
            cfg.setDirectoryForTemplateLoading(tempFoldFile);
            cfg.setDefaultEncoding("UTF-8");
            cfg.setTemplateUpdateDelay(0);
            cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
            // **********獲取freemaker模板**********
            dateTmp = cfg.getTemplate(tampPath);

            // **********將數據寫入freemaker模板**********
            fw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(new File(file)), "UTF-8"));
            dateTmp.process(exlParam, fw);

            // **********從freemaker模板讀出數據寫到Excel表格並生成出來**********
            String fileDir = "excel";
            // 文件保存目錄  項目目錄下面
            String filePath =  new File("").getAbsolutePath();
            // 生成保存文件路徑
            String createPath = filePath + "/" + fileDir + "/";
            // 構建源文件
            File files = new File(file);
            // 文件夾不存在就創建
            createFolder(createPath);
            // 刪除原來的文件
            deleteFile(createPath + excelName);
            // 構建目標文件
            File fileCopy = new File(createPath + excelName);
            // 目標文件不存在就創建
            if (!(fileCopy.exists())) {
                fileCopy.createNewFile();
            }
            // 源文件創建輸入流
            in = new FileInputStream(files);
            // 目標文件創建輸出流
            out = new FileOutputStream(fileCopy, true);
            // 創建字節數組
            byte[] temp = new byte[1024];
            int length = 0;
            // 源文件讀取一部分內容
            while ((length = in.read(temp)) != -1) {
                // 目標文件寫入一部分內容
                out.write(temp, 0, length);
            }
            // 資源服務器訪問目錄 這邊需要配置tomcat的虛擬路徑,就可以直接在url上面下載表格了
            String serverPath = "resourceServer";
            String savePath = "/" + serverPath + "/" + fileDir + "/" + excelName;
            // 服務器圖片訪問目錄
            return savePath;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        } finally {
            try {
                fw.close();
                // 關閉文件輸入輸出流
                in.close();
                out.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

        }

    }

    // 創建文件
    public static boolean createFolder(String path) {
        File file = new File(path);
        if (!file.exists()) {
            return file.mkdir();
        } else {
            return true;
        }
    }

    public static boolean deleteFile(String filePath) {// 刪除單個文件
        boolean flag = false;
        File file = new File(filePath);
        if (file.exists() && file.isFile()) {
            file.delete();// 文件刪除
            flag = true;
        }
        return true;
    }

}

這個也不用多說,里面注釋基本上已經解釋清楚了,

  • 因為數據放到freemaker模板里面了所以只需要使用freemaker模板的語法取出數據存放在模板里面就可以了

  • Excel導出打開出現問題的原因
    當office2010之前的版本打開會出現格式不正確的提示,然后點擊確定之后還是報格式錯誤或者可以打開但是沒有數據,這種解決方法只需要將ss:ExpandedRowCount這個值設置和行數相等或者設置大一點就不會出現這種問題了。

    錯誤提示

    Demo地址:https://files.cnblogs.com/files/yangk1996/FreeMaker.zip


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM