jfree+easypoi實(shí)現(xiàn)數(shù)據(jù)報表導(dǎo)出下載

基于springboot+mybatis,數(shù)據(jù)庫mysql

模板樣例:
模板樣例.png
效果樣例:
圖表效果.png

1.pom文件

        <!--報表相關(guān)-->
        <dependency>
            <groupId>cn.afterturn</groupId>
            <artifactId>easypoi-base</artifactId>
            <version>4.1.0</version>
        </dependency>
        <dependency>
            <groupId>org.jfree</groupId>
            <artifactId>jcommon</artifactId>
            <version>1.0.24</version>
        </dependency>
        <dependency>
            <groupId>org.jfree</groupId>
            <artifactId>jfreechart</artifactId>
            <version>1.5.0</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-freemarker</artifactId>
        </dependency>

2.JfreeUtil 文件(用于生成圖表西设,更多圖表樣式等前往官網(wǎng)查找)

package com.bonc.huanghai.manage.util;

import cn.afterturn.easypoi.entity.ImageEntity;
import lombok.extern.slf4j.Slf4j;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartUtils;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.StandardChartTheme;
import org.jfree.chart.axis.CategoryAxis;
import org.jfree.chart.axis.CategoryLabelPositions;
import org.jfree.chart.labels.StandardCategoryItemLabelGenerator;
import org.jfree.chart.labels.StandardPieSectionLabelGenerator;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.plot.DatasetRenderingOrder;
import org.jfree.chart.plot.PiePlot;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.renderer.category.BarRenderer;
import org.jfree.chart.renderer.category.LineAndShapeRenderer;
import org.jfree.chart.renderer.category.StackedBarRenderer;
import org.jfree.chart.renderer.category.StandardBarPainter;
import org.jfree.data.category.CategoryDataset;
import org.jfree.data.category.DefaultCategoryDataset;
import org.jfree.data.general.DefaultPieDataset;
import org.springframework.util.Assert;

import java.awt.*;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.List;


/**
 * @ClassName:JfreeUtil
 * @author:莫須有
 * @Description: 生成word文檔中的圖表(JPG)
 * @create:2020/2/13 19:22
 * @Version1.0
 */

@Slf4j
public class JfreeUtil {
    /**
     * 臨時文件存儲实束,也可以設(shè)置讀取配置文件
     */
    private static String tempImgPath = "/data/app/server/weixin/tempJfree.jpeg";
    /**
     * 橫縱軸等字體
     */
    private static Font font = new Font("宋體", Font.PLAIN, 12);
    /**
     *  顏色循環(huán)列表
     */
    private static final Paint[] COLORS = { new Color(65, 105, 255),new Color(0, 191, 255),
                                            new Color(30, 144, 223),new Color(30, 70, 255),
                                            new Color(0, 0, 200), new Color(0, 0, 150)
                                            };

    /**
     * 將圖片轉(zhuǎn)化為字節(jié)數(shù)組
     * @return 字節(jié)數(shù)組
     */
    private static byte[] imgToByte(){
        File file = new File(tempImgPath);
        byte[] buffer = null;
        FileInputStream fis = null;
        ByteArrayOutputStream bos = null;
        try {
            fis = new FileInputStream(file);
            bos = new ByteArrayOutputStream(1000);
            byte[] b = new byte[1000];
            int n;
            while ((n = fis.read(b)) != -1) {
                bos.write(b, 0, n);
            }
            buffer = bos.toByteArray();
        } catch (IOException e) {
            log.error(e.getMessage());
        }finally {
            try {
                if(fis != null) {
                    fis.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if(bos!= null) {
                    bos.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            //刪除臨時文件
            file.delete();

        }
        return buffer;
    }

    /**
     * 生成主題樣式,及避免亂碼
     * @return standardChartTheme
     */
    private static StandardChartTheme getChartTheme() {
        // 處理中文亂碼
        // 創(chuàng)建主題樣式
        StandardChartTheme standardChartTheme = new StandardChartTheme("CN");
        //設(shè)置標(biāo)題字體
        standardChartTheme.setExtraLargeFont(new Font("宋體", Font.BOLD, 15));
        //設(shè)置圖例的字體
        standardChartTheme.setRegularFont(new Font("宋體", Font.PLAIN, 12));
        //設(shè)置軸向的字體
        standardChartTheme.setLargeFont(new Font("宋體", Font.PLAIN, 12));
        return standardChartTheme;
    }

    /**
     * 生成餅圖
     * @param title 標(biāo)題
     * @param data 數(shù)據(jù)集 {String,Number}
     * @param width 圖片寬度
     * @param height 圖片高度
     * @return 圖像對象
     */
    public static ImageEntity pieChart(String title, List<Object[]> data, int width, int height) {

        //設(shè)置主題樣式
        StandardChartTheme standardChartTheme = JfreeUtil.getChartTheme();
        ChartFactory.setChartTheme(standardChartTheme);

        //根據(jù)jfree生成一個本地餅狀圖數(shù)據(jù)集
        DefaultPieDataset dataset = new DefaultPieDataset();
        for (Object[] arr : data) {
            dataset.setValue((String) arr[0], (Number) arr[1]);
        }
        //創(chuàng)建圖表  (圖標(biāo)標(biāo)題万细、數(shù)據(jù)集合辆沦、是否顯示圖例標(biāo)識友瘤、是否顯示tooltips权烧、是否支持超鏈接)
        JFreeChart chart = ChartFactory.createPieChart(title, dataset, true, false, false);

        //設(shè)置抗鋸齒
        chart.setTextAntiAlias(false);
        //圖例
        chart.getLegend().setItemFont(font);
        //圖片邊框
        chart.setBorderVisible(true);
        chart.setBorderPaint(Color.gray);
        //得到繪圖區(qū)
        PiePlot plot = (PiePlot) chart.getPlot();
        plot.setNoDataMessage("暫無數(shù)據(jù)");
        //忽略無值的分類
        plot.setIgnoreNullValues(true);
        plot.setBackgroundAlpha(0f);
        plot.setOutlineVisible(false);
        //設(shè)置標(biāo)簽陰影顏色
        plot.setShadowPaint(new Color(255,255,255));
        //設(shè)置標(biāo)簽生成器(默認(rèn){0})
        plot.setLabelGenerator(new StandardPieSectionLabelGenerator("{0}({1})/{2}"));
        //設(shè)置標(biāo)簽字體
        plot.setLabelFont(font);
        //設(shè)置標(biāo)簽背景色
        plot.setLabelBackgroundPaint(new Color(255,255,255));
        //扇區(qū)分離與顏色設(shè)置
        for (int i=0;i<dataset.getItemCount();i++) {
            plot.setExplodePercent(dataset.getKey(i), 0.02);
            plot.setSectionPaint(dataset.getKey(i).toString(), COLORS[i % COLORS.length]);
        }

        try {
            ChartUtils.saveChartAsJPEG(new File(tempImgPath), chart, width, height);
        } catch (IOException e1) {
            log.error("生成餅狀圖失斆幸唷!");
        }
        ImageEntity imageEntity = new ImageEntity(imgToByte(), width, height);
        Assert.notNull(imageEntity.getData(),"生成餅狀圖對象失敯懵搿妻率!");
        return imageEntity;
    }



    public static ImageEntity barChart(String title, String xName, String yName, List<Object[]> data, int width, int height){
        return barChart(title, xName, yName, data,width,height,false);
    }

    /**
     * 生成垂直柱形圖
     * @param title
     * @param xName
     * @param yName
     * @param data
     * @param width
     * @param height
     * @param legend
     * @return 圖片
     */
    public static ImageEntity barChart(String title, String xName, String yName, List<Object[]> data, int width, int height,Boolean legend) {
        //設(shè)置主題樣式
        StandardChartTheme standardChartTheme = JfreeUtil.getChartTheme();
        ChartFactory.setChartTheme(standardChartTheme);

        //數(shù)據(jù)集
        DefaultCategoryDataset dataset = new DefaultCategoryDataset();
        for (Object[] arr : data) {
            dataset.setValue((Number) arr[0], (String) arr[1],(String) arr[2]);
        }

        //創(chuàng)建圖表
        JFreeChart chart = ChartFactory.createBarChart(title, xName,yName,dataset, PlotOrientation.VERTICAL,legend,true,false);
        //設(shè)置抗鋸齒
        chart.setTextAntiAlias(false);
        //圖片邊框
        chart.setBorderVisible(true);
        chart.setBorderPaint(Color.gray);


        //得到繪圖區(qū)
        CategoryPlot plot = (CategoryPlot) chart.getPlot();

        //獲取渲染對象
        BarRenderer barRenderer = (BarRenderer)plot.getRenderer();
        //設(shè)置柱形圖的寬度
        barRenderer.setMaximumBarWidth(0.07);
        //最短的BAR長度,避免數(shù)值太小而顯示不出
        barRenderer.setMinimumBarLength(0.5);
        // 設(shè)置柱形圖上的文字偏離值
        barRenderer.setItemLabelAnchorOffset(10D);
        //設(shè)置柱子的最大寬度
        // 設(shè)置柱狀圖之間的距離0.1代表10%
        barRenderer.setItemMargin(0.000000005);
        //設(shè)置柱子為平面圖不是立體的
        barRenderer.setBarPainter(new StandardBarPainter());
        // 設(shè)置顏色
        barRenderer.setSeriesPaint(0,new Color(65,105,225));
        //不顯示陰影
        barRenderer.setShadowVisible(false);
        //顯示數(shù)值
        barRenderer.setDefaultItemLabelGenerator(new StandardCategoryItemLabelGenerator());
        barRenderer.setDefaultItemLabelFont(font);
        barRenderer.setItemLabelAnchorOffset(0.1D);
        barRenderer.setDefaultItemLabelsVisible(true);
        for (int i=0;i<dataset.getRowCount();i++) {
            barRenderer.setSeriesPaint(i, COLORS[i % COLORS.length]);
        }

        CategoryAxis domainAxis = plot.getDomainAxis();
        // 右邊距 邊框距離,防止最后邊的一個數(shù)據(jù)靠近了坐標(biāo)軸侈询。
        domainAxis.setUpperMargin(0.06);
        // 橫軸 lable 的位置 橫軸上的 Lable 45度傾斜
        domainAxis.setCategoryLabelPositions(CategoryLabelPositions.UP_45);

        //設(shè)置網(wǎng)格背景顏色
        plot.setBackgroundPaint(Color.white);
        //設(shè)置網(wǎng)格橫線顏色
        plot.setRangeGridlinePaint(Color.black);
        //得到繪圖區(qū)的域軸(橫軸),設(shè)置標(biāo)簽的字體
        plot.getDomainAxis().setLabelFont(font);
        //設(shè)置橫軸標(biāo)簽項字體
        plot.getDomainAxis().setTickLabelFont(font);
        //設(shè)置范圍軸(縱軸)字體
        plot.getRangeAxis().setLabelFont(font);
        //設(shè)置外邊框不可見
        plot.setOutlineVisible(false);

        try {
            ChartUtils.saveChartAsJPEG(new File(tempImgPath), chart, width, height);
        } catch (IOException e1) {
            log.error("生成柱形圖失斏嗾恰!");
        }
        ImageEntity imageEntity = new ImageEntity(imgToByte(), width, height);
        Assert.notNull(imageEntity.getData(),"生成柱形圖對象失敗囊嘉!");
        return imageEntity;
    }

    /**
     *  堆疊柱形圖
     * @param title
     * @param xName
     * @param yName
     * @param data
     * @param width
     * @param height
     * @return
     */
    public static ImageEntity stackedBarChart(String title, String xName, String yName, List<Object[]> data, int width, int height) {

        //設(shè)置主題樣式
        StandardChartTheme standardChartTheme = JfreeUtil.getChartTheme();
        ChartFactory.setChartTheme(standardChartTheme);


        //數(shù)據(jù)集
        DefaultCategoryDataset dataset = new DefaultCategoryDataset();
        for (Object[] arr : data) {
            dataset.setValue((Number) arr[0], (String) arr[1],(String) arr[2]);
        }
        //圖標(biāo)標(biāo)題温技、數(shù)據(jù)集合、是否顯示圖例標(biāo)識扭粱、是否顯示tooltips舵鳞、是否支持超鏈接
        JFreeChart chart = ChartFactory.createStackedBarChart(title, xName,yName,dataset);
        //設(shè)置抗鋸齒
        chart.setTextAntiAlias(false);
        //設(shè)置提示條字體
        chart.getLegend().setItemFont(font);
        //圖片邊框
        chart.setBorderVisible(true);
        chart.setBorderPaint(Color.gray);

        //得到繪圖區(qū)
        CategoryPlot plot = (CategoryPlot) chart.getPlot();

        //獲取渲染對象
        StackedBarRenderer stackedBarRenderer = (StackedBarRenderer)plot.getRenderer();
        //設(shè)置柱形圖的寬度
        stackedBarRenderer.setMaximumBarWidth(0.07);
        //最短的BAR長度,避免數(shù)值太小而顯示不出
        stackedBarRenderer.setMinimumBarLength(0.5);
        // 設(shè)置柱形圖上的文字偏離值
        stackedBarRenderer.setItemLabelAnchorOffset(10D);
        //設(shè)置柱子的最大寬度
        // 設(shè)置柱狀圖之間的距離0.1代表10%
        stackedBarRenderer.setItemMargin(0.000000005);
        //設(shè)置柱子為平面圖不是立體的
        stackedBarRenderer.setBarPainter(new StandardBarPainter());
        //不顯示陰影
        stackedBarRenderer.setShadowVisible(false);
        //設(shè)置顏色
        for (int i=0;i<dataset.getRowCount();i++) {
            stackedBarRenderer.setSeriesPaint(i, COLORS[i % COLORS.length]);
        }
        //顯示數(shù)值
        stackedBarRenderer.setDefaultItemLabelGenerator(new StandardCategoryItemLabelGenerator());
        stackedBarRenderer.setDefaultItemLabelFont(font);
        stackedBarRenderer.setItemLabelAnchorOffset(0.1D);
        stackedBarRenderer.setDefaultItemLabelsVisible(true);

        CategoryAxis domainAxis = plot.getDomainAxis();
        // 右邊距 邊框距離,防止最后邊的一個數(shù)據(jù)靠近了坐標(biāo)軸琢蛤。
        domainAxis.setUpperMargin(0.06);
        // 橫軸 lable 的位置 橫軸上的 Lable 45度傾斜
        domainAxis.setCategoryLabelPositions(CategoryLabelPositions.UP_45);


        //設(shè)置網(wǎng)格背景顏色
        plot.setBackgroundPaint(Color.white);
        //設(shè)置網(wǎng)格橫線顏色
        plot.setRangeGridlinePaint(Color.black);
        //得到繪圖區(qū)的域軸(橫軸),設(shè)置標(biāo)簽的字體
        plot.getDomainAxis().setLabelFont(font);
        //設(shè)置橫軸標(biāo)簽項字體
        plot.getDomainAxis().setTickLabelFont(font);
        //設(shè)置范圍軸(縱軸)字體
        plot.getRangeAxis().setLabelFont(font);
        //設(shè)置外邊框不可見
        plot.setOutlineVisible(false);

        try {
            ChartUtils.saveChartAsJPEG(new File(tempImgPath), chart, width, height);
        } catch (IOException e1) {
            log.error("生成柱形圖失旘讯椤!");
        }
        ImageEntity imageEntity = new ImageEntity(imgToByte(), width, height);
        Assert.notNull(imageEntity.getData(),"生成柱形圖對象失敳┢洹套才!");
        return imageEntity;
    }

    /**
     * 折線圖 柱形圖 組合
     * @param title
     * @param xName
     * @param yName
     * @param barData
     * @param lineData
     * @param width
     * @param height
     * @return
     */
    public static ImageEntity lineBarChart(String title, String xName, String yName, List<Object[]> barData, List<Object[]> lineData,int width, int height) {

        //設(shè)置主題樣式
        StandardChartTheme standardChartTheme = JfreeUtil.getChartTheme();
        ChartFactory.setChartTheme(standardChartTheme);

        //數(shù)據(jù)集
        DefaultCategoryDataset barDataset = new DefaultCategoryDataset();
        for (Object[] arr : barData) {
            barDataset.setValue((Number) arr[0], (String) arr[1],(String) arr[2]);
        }
        //數(shù)據(jù)集
        DefaultCategoryDataset lineDataset = new DefaultCategoryDataset();
        for (Object[] arr : lineData) {
            lineDataset.setValue((Number) arr[0], (String) arr[1],(String) arr[2]);
        }

        //圖標(biāo)標(biāo)題、數(shù)據(jù)集合慕淡、是否顯示圖例標(biāo)識背伴、是否顯示tooltips、是否支持超鏈接
        JFreeChart chart = ChartFactory.createBarChart(title, xName,yName,barDataset,PlotOrientation.VERTICAL,false,true,false);
        //設(shè)置抗鋸齒
        chart.setTextAntiAlias(false);
        //圖片邊框
        chart.setBorderVisible(true);
        chart.setBorderPaint(Color.gray);

        //得到繪圖區(qū)
        CategoryPlot plot = (CategoryPlot) chart.getPlot();

        //設(shè)置網(wǎng)格背景顏色
        plot.setBackgroundPaint(Color.white);
        //設(shè)置網(wǎng)格橫線顏色
        plot.setRangeGridlinePaint(Color.black);
        //得到繪圖區(qū)的域軸(橫軸),設(shè)置標(biāo)簽的字體
        plot.getDomainAxis().setLabelFont(font);
        //設(shè)置橫軸標(biāo)簽項字體
        plot.getDomainAxis().setTickLabelFont(font);
        //設(shè)置范圍軸(縱軸)字體
        plot.getRangeAxis().setLabelFont(font);
        //設(shè)置外邊框不可見
        plot.setOutlineVisible(false);

        //獲取渲染對象
        BarRenderer barRenderer = (BarRenderer)plot.getRenderer();
        //設(shè)置柱形圖的寬度
        barRenderer.setMaximumBarWidth(0.07);
        //最短的BAR長度峰髓,避免數(shù)值太小而顯示不出
        barRenderer.setMinimumBarLength(0.5);
        // 設(shè)置柱形圖上的文字偏離值
        barRenderer.setItemLabelAnchorOffset(10D);
        //設(shè)置柱子的最大寬度
        // 設(shè)置柱狀圖之間的距離0.1代表10%
        barRenderer.setItemMargin(0.000000005);
        //設(shè)置柱子為平面圖不是立體的
        barRenderer.setBarPainter(new StandardBarPainter());
        // 設(shè)置顏色
        barRenderer.setSeriesPaint(0,new Color(65,105,225));
        //不顯示陰影
        barRenderer.setShadowVisible(false);
        //顯示數(shù)值
        barRenderer.setDefaultItemLabelGenerator(new StandardCategoryItemLabelGenerator());
        barRenderer.setDefaultItemLabelFont(font);
        barRenderer.setItemLabelAnchorOffset(0.1D);
        barRenderer.setDefaultItemLabelsVisible(true);

        CategoryAxis domainAxis = plot.getDomainAxis();
        // 右邊距 邊框距離,防止最后邊的一個數(shù)據(jù)靠近了坐標(biāo)軸傻寂。
        domainAxis.setUpperMargin(0.06);
        // 橫軸 lable 的位置 橫軸上的 Lable 45度傾斜
        domainAxis.setCategoryLabelPositions(CategoryLabelPositions.UP_45);

        //放折線圖數(shù)據(jù)
        CategoryDataset categorydataset = lineDataset;
        // 0顯示是柱狀圖,1顯示折線圖
        plot.setDataset(1, categorydataset);
        // 顯示折線圖携兵,0疾掰,0坐標(biāo)軸都在左側(cè)
        plot.mapDatasetToRangeAxis(0, 0);
        plot.setDatasetRenderingOrder(DatasetRenderingOrder.FORWARD);
        //畫折線圖
        LineAndShapeRenderer lineandshaperenderer = new LineAndShapeRenderer();
        // 設(shè)置實(shí)線
        BasicStroke realLine = new BasicStroke(3.0f);
        lineandshaperenderer.setSeriesStroke(0, realLine);
        //去掉折線的點(diǎn)
        lineandshaperenderer.setDefaultShapesVisible(false);
        //顯示數(shù)值
        lineandshaperenderer.setDefaultItemLabelGenerator(new StandardCategoryItemLabelGenerator());
        lineandshaperenderer.setDefaultItemLabelFont(font);
        lineandshaperenderer.setDefaultItemLabelPaint(new Color(80,30,0));
        lineandshaperenderer.setItemLabelAnchorOffset(0.2D);
        lineandshaperenderer.setDefaultItemLabelsVisible(true);
        plot.setRenderer(1, lineandshaperenderer);

        try {
            ChartUtils.saveChartAsJPEG(new File(tempImgPath), chart, width, height);
        } catch (IOException e1) {
            log.error("生成折線柱形圖失敗徐紧!");
        }
        ImageEntity imageEntity = new ImageEntity(imgToByte(), width, height);
        Assert.notNull(imageEntity.getData(),"生成折線柱形圖對象失斁裁省!");
        return imageEntity;
    }
}

2.DownReportUtil 文件(下載生成的文件)

package com.bonc.huanghai.manage.util;

import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.activation.MimetypesFileTypeMap;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;

/**
 * @author:莫須有
 * @Description: 下載文件工具類
 * @create:2020/3/9 9:35
 * @Version1.0
 */
public class DownReportUtil {

    /**
     * 下載文件,可以下載后刪除
     * @param pathname
     * @param fileName
     * @throws IOException
     */
    public static void download(String pathname, String fileName) throws IOException {
        // 讀取filename
        File file = new File(pathname);
        BufferedInputStream bis = null;
        OutputStream outputStream = null;
        if (file.isFile() && file.exists()) {
            try {
                ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
                HttpServletResponse response = requestAttributes.getResponse();
                // 設(shè)置信息給客戶端不解析
                String type = new MimetypesFileTypeMap().getContentType(fileName);
                // 設(shè)置contenttype并级,即告訴客戶端所發(fā)送的數(shù)據(jù)屬于什么類型
                response.setHeader("Content-type", type);
                // 設(shè)置編碼
                String encoded = URLEncoder.encode(fileName, "utf-8");
                // 設(shè)置擴(kuò)展頭巴柿,當(dāng)Content-Type 的類型為要下載的類型時 , 這個信息頭會告訴瀏覽器這個文件的名字和類型。
                response.setHeader("Content-Disposition", "attachment;filename=" + encoded);
                // 發(fā)送給客戶端的數(shù)據(jù)
                outputStream = response.getOutputStream();

                byte[] buff = new byte[1024];
                bis = new BufferedInputStream(new FileInputStream(file));
                //office打開異常
/*                int i = bis.read(buff);
                while (i != -1) {
                    outputStream.write(buff, 0, buff.length);
                    outputStream.flush();
                    i = bis.read(buff);
                }*/
                //office打開正常,但是QQ瀏覽器下載會異常
                int len = 0;
                while ((len = bis.read(buff)) >= 0) {
                    outputStream.write(buff, 0, len);
                    outputStream.flush();
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                //關(guān)閉流
                try {
                    if (bis != null) {
                        bis.close();
                    }
                    if (outputStream != null) {
                        outputStream.close();
                    }
                } catch (Exception e2) {
                    e2.printStackTrace();
                }
                // 文件刪除
                file.delete();
            }
        }
    }
}

2.WordUtil(用于生成最終word)

package com.bonc.huanghai.manage.util;

import cn.afterturn.easypoi.word.WordExportUtil;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.springframework.util.Assert;

import java.io.File;
import java.io.FileOutputStream;
import java.util.Map;


/**
 * @ClassName:WordUtil
 * @author:莫須有
 * @Description: 導(dǎo)出word 只支持docx
 * @create:2020/2/13 19:23
 * @Version1.0
 */
public class WordUtil {

    /**
     * 導(dǎo)出word
     * <p>第一步生成替換后的word文件死遭,只支持docx</p>
     * <p>第二步下載生成的文件</p>
     * <p>第三步刪除生成的臨時文件</p>
     * 模版變量中變量格式:{{foo}}
     *
     * @param templatePath word模板地址
     * @param temDir       生成臨時文件存放地址
     * @param fileName     文件名
     * @param params       替換的參數(shù)
     */
    public static void exportWord(String templatePath, String temDir, String fileName, Map<String, Object> params) {
        Assert.notNull(templatePath, "模板路徑不能為空");
        Assert.notNull(temDir, "臨時文件路徑不能為空");
        Assert.notNull(fileName, "導(dǎo)出文件名不能為空");
        Assert.isTrue(fileName.endsWith(".docx"), "word導(dǎo)出請使用docx格式");
        if (!temDir.endsWith("/")) {
            temDir = temDir + File.separator;
        }
        File dir = new File(temDir);
        if (!dir.exists()) {
            dir.mkdirs();
        }
        try {
            XWPFDocument doc = WordExportUtil.exportWord07(templatePath, params);
            String tmpPath = temDir + fileName;
            FileOutputStream fos = new FileOutputStream(tmpPath);
            doc.write(fos);
            fos.flush();
            fos.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
package com.bonc.huanghai.manage.service.report.impl;

import cn.afterturn.easypoi.entity.ImageEntity;
import com.bonc.huanghai.manage.model.count.Count;
import com.bonc.huanghai.manage.model.ticket.TicketInfo;
import com.bonc.huanghai.manage.model.tourist.TouristOrigin;
import com.bonc.huanghai.manage.util.DownReportUtil;
import com.bonc.huanghai.manage.util.JfreeUtil;
import com.bonc.huanghai.manage.util.WordUtil;
import com.bonc.huanghai.manage.mapper.count.ITouristPortraitMapper;
import com.bonc.huanghai.manage.mapper.count.LyricalCountMapper;
import com.bonc.huanghai.manage.mapper.oa.TicketMapper;
import com.bonc.huanghai.manage.service.report.ReportService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;

import java.io.File;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @ClassName:ReportServiceImpl
 * @author:莫須有
 * @Description: 導(dǎo)出報表
 * @create:2020/3/2 15:47
 * @Version1.0
 */
@Service
@Primary
public class ReportServiceImpl implements ReportService {
    private static final String PERCENT_SIGN = "%";
    private static final String TEM_DIR = "tjs/tjs-manage/src/main/resources/templates/download/";
    private static final String TEMPLATE_PATH = "templates/數(shù)據(jù)報告模板.docx";
    private static final String DOCX = ".docx";
    private static final String DATA_ERROR = "(暫無數(shù)據(jù))";
    private static final String DATA_PICTURE_ERROR = "(圖片中數(shù)據(jù)暫無)";
    private static final String DATA_FIGURE_ERROR = "0";
    private static final Integer WIDTH = 550;
    private static final Integer HEIGHT = 400;


    @Autowired
    TicketMapper ticketMapper;
    @Autowired
    ITouristPortraitMapper iTouristPortraitMapper;
    @Autowired
    LyricalCountMapper lyricalCountMapper;

    /**
     * 生成百分比
     * @param proportionDouble
     * @return
     */
    private String proportionInit(double proportionDouble) {
        String format = new DecimalFormat("0").format(BigDecimal.valueOf(proportionDouble).multiply(new BigDecimal(100)));
        String str = format + PERCENT_SIGN;
        return str;
    }

    /**
     * 導(dǎo)出景區(qū)數(shù)據(jù)分析報告
     * @param title
     * @param beginDate
     * @param endDate
     * @return
     */
    @Override
    public String downloadReport(String title, String beginDate, String endDate) {

        HashMap<String, Object> map = new HashMap<>(40);
        if (title == null || title.length() == 0){
            title = "景區(qū)_"+beginDate+"-"+endDate+"_數(shù)據(jù)分析報告";
        }
        //標(biāo)題,起止時間
        map.put("title", title);
        map.put("beginDate", beginDate);
        map.put("endDate", endDate);

        // 獲取當(dāng)前時間
        SimpleDateFormat sdf = new SimpleDateFormat();
        sdf.applyPattern("yyyy年MM月dd日");
        Date date = new Date();
        map.put("date", sdf.format(date));

        //游客畫像分析
        //省內(nèi)外游客客流量
        map.putAll(provincialSourceToReporttPic(beginDate, endDate));
        //國內(nèi)游客畫像,省外游客
        map.putAll(outofprovinceSourceRankingPic(beginDate, endDate));
        //國內(nèi)游客畫像,省內(nèi)游客
        map.putAll(provincialSourceRankingPic(beginDate, endDate));
        //游客年齡段分布
        map.putAll(ageProportionPic(beginDate, endDate));
        //游客男女性別分布
        map.putAll(sexProportionPic(beginDate, endDate));
        //游客交通方式分析
        map.putAll(transportationProportionPic(beginDate, endDate));
        //游客消費(fèi)潛力分析
        map.putAll(consumptionLevelPic(beginDate, endDate));
        //車輛來源分析
        map.putAll(carOriginPic(beginDate, endDate));
        //門票匯總分析
        map.putAll(ticketPic(beginDate, endDate));
        //輿情分析
        map.putAll(lyricalPic(beginDate, endDate));

        //導(dǎo)出word
        String fileName = title + DOCX;
        WordUtil.exportWord(TEMPLATE_PATH, TEM_DIR, fileName, map);

        //下載文件
        try {
            DownReportUtil.download(TEM_DIR + fileName, fileName);
        } catch (Exception e) {
            e.printStackTrace();
        }
        File file = new File(TEM_DIR + fileName);
        // 文件刪除
        if (file.isFile() && file.exists()) {
            file.delete();
        }
        return "OK";
    }

   /**
     * 游客畫像分析
     * 省內(nèi)外游客客流量
     *
     * @param beginDate
     * @param endDate
     * @return map (2)
     */
    private HashMap<String, Object> provincialSourceToReporttPic(String beginDate, String endDate) {
        HashMap<String, Object> map = new HashMap<>(2);

        //省內(nèi)外+未知等的總游客數(shù)量
        int sumOfAllTourist = 0;
        try {
        /*
        存放進(jìn)柱狀圖的數(shù)據(jù)集
         */
            List<Object[]> provincialSourceToReportPicData = new ArrayList<Object[]>();
        /*
        存放數(shù)據(jù)庫取出的數(shù)據(jù)
         */
            List<TouristOrigin> provincialSourceToReport = iTouristPortraitMapper.provincialSourceToReport(beginDate, endDate);
        /*
        將數(shù)據(jù)庫取出的數(shù)據(jù)放入柱狀圖的數(shù)據(jù)集
         */
            for (TouristOrigin data : provincialSourceToReport) {
                if (data.getInProvince() == 0) {
                    provincialSourceToReportPicData.add(new Object[]{data.getCount(), "省外", data.getDate()});
                }
                if (data.getInProvince() == 1) {
                    provincialSourceToReportPicData.add(new Object[]{data.getCount(), "省內(nèi)", data.getDate()});
                }
                sumOfAllTourist = sumOfAllTourist + data.getCount();
            }
            /*
            判斷數(shù)據(jù)是否為空或0,若為空或零則直接當(dāng)做異常處理
             */
            if (provincialSourceToReport == null || provincialSourceToReport.size()==0 || sumOfAllTourist ==0) {
                throw new Exception();
            }
        /*
        生成柱狀圖的圖片
         */
            ImageEntity provincialSourceToReporttPic = JfreeUtil.stackedBarChart("省內(nèi)外游客流量", "", "游客數(shù)量", provincialSourceToReportPicData, WIDTH, HEIGHT);
        /*
        放入文檔對應(yīng)的map集合中
         */
            map.put("provincialSourceToReporttPic", provincialSourceToReporttPic);
            map.put("游客總計", sumOfAllTourist);
        }catch (Exception e){
            e.printStackTrace();
            map.put("provincialSourceToReporttPic", DATA_PICTURE_ERROR);
            map.put("游客總計", DATA_FIGURE_ERROR);
        }
        return map;
    }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末广恢,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子呀潭,更是在濱河造成了極大的恐慌钉迷,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,548評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件钠署,死亡現(xiàn)場離奇詭異糠聪,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)谐鼎,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,497評論 3 399
  • 文/潘曉璐 我一進(jìn)店門舰蟆,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事身害∥肚模” “怎么了?”我有些...
    開封第一講書人閱讀 167,990評論 0 360
  • 文/不壞的土叔 我叫張陵塌鸯,是天一觀的道長侍瑟。 經(jīng)常有香客問我,道長丙猬,這世上最難降的妖魔是什么涨颜? 我笑而不...
    開封第一講書人閱讀 59,618評論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮茧球,結(jié)果婚禮上庭瑰,老公的妹妹穿的比我還像新娘。我一直安慰自己抢埋,他們只是感情好见擦,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,618評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著羹令,像睡著了一般。 火紅的嫁衣襯著肌膚如雪损痰。 梳的紋絲不亂的頭發(fā)上福侈,一...
    開封第一講書人閱讀 52,246評論 1 308
  • 那天,我揣著相機(jī)與錄音卢未,去河邊找鬼肪凛。 笑死,一個胖子當(dāng)著我的面吹牛辽社,可吹牛的內(nèi)容都是我干的伟墙。 我是一名探鬼主播,決...
    沈念sama閱讀 40,819評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼滴铅,長吁一口氣:“原來是場噩夢啊……” “哼戳葵!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起汉匙,我...
    開封第一講書人閱讀 39,725評論 0 276
  • 序言:老撾萬榮一對情侶失蹤拱烁,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后噩翠,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體戏自,經(jīng)...
    沈念sama閱讀 46,268評論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,356評論 3 340
  • 正文 我和宋清朗相戀三年伤锚,在試婚紗的時候發(fā)現(xiàn)自己被綠了擅笔。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,488評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖猛们,靈堂內(nèi)的尸體忽然破棺而出念脯,到底是詐尸還是另有隱情,我是刑警寧澤阅懦,帶...
    沈念sama閱讀 36,181評論 5 350
  • 正文 年R本政府宣布和二,位于F島的核電站,受9級特大地震影響耳胎,放射性物質(zhì)發(fā)生泄漏惯吕。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,862評論 3 333
  • 文/蒙蒙 一怕午、第九天 我趴在偏房一處隱蔽的房頂上張望废登。 院中可真熱鬧,春花似錦郁惜、人聲如沸堡距。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,331評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽羽戒。三九已至,卻和暖如春虎韵,著一層夾襖步出監(jiān)牢的瞬間易稠,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,445評論 1 272
  • 我被黑心中介騙來泰國打工包蓝, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留驶社,地道東北人。 一個月前我還...
    沈念sama閱讀 48,897評論 3 376
  • 正文 我出身青樓亡电,卻偏偏與公主長得像,于是被迫代替她去往敵國和親硅瞧。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,500評論 2 359

推薦閱讀更多精彩內(nèi)容