天天看點

Java 使用freemaker導出word(帶echarts圖檔和表格)

一.導入freemaker和Echarts的jar包

      下載下傳位址:https://mvnrepository.com/

Java 使用freemaker導出word(帶echarts圖檔和表格)

 二. 制作模闆

1.把需要替換的内容或圖檔用xxx替換(也可以直接用${xxx}格式,不過轉xml的時候會被拆分開)。

2.表格隻需要畫一行,循環在xml中配置

Java 使用freemaker導出word(帶echarts圖檔和表格)

3.如果多張圖檔的話,一定要選擇不同的圖檔,不能為了省事使用同一張圖檔!

4.模闆畫好以後另存為xml格式,然後關掉word。

Java 使用freemaker導出word(帶echarts圖檔和表格)

(一定要選Word 2003 XML文檔!!!血的教訓啊!!!)

5.用notepad++打開你儲存的xml格式的文檔 Ctrl+F找到你之前定義的單詞,用${}包住。如圖:

Java 使用freemaker導出word(帶echarts圖檔和表格)

替換圖檔,搜尋<pkg:binaryData>,把文檔中的這些内容(這些内容就是插入圖檔的BASE64字元串)删掉 換成${imageName}這種名稱的

Java 使用freemaker導出word(帶echarts圖檔和表格)

循環生成表格

找到表格的<w:tr>标簽,在<w:tr>标簽前加上<#list listName as list>,在</w:tr>後邊加上</#list>,list标簽可以使标簽内的表格自動循環生成相應的行數,listName就是你背景的資料, list是個别名,中間每個字段需要改成${list.xxx}格式。

Java 使用freemaker導出word(帶echarts圖檔和表格)

完成模闆,儲存并關閉xml,修改檔案的名稱,改成.ftl格式的。(最後儲存一份xml,友善以後修改,xml模闆千萬不要用word打開!!!)

三.Java代碼

1.生成資料并傳回集合

public static Map<String, Object> parseToMap(String date, String jrgl, 

            List<Map<String, Object>> list_CBQS) {

        Map<String, Object> datas = new HashMap();

        datas.put("rb_date", date);

        datas.put("text_JRGL", jrgl);

        datas.put("text_CBQS", text_CBQS);

        datas.put("text_XXFB", text_XXFB);

        datas.put("text_QGQX", text_QGQX);

        此處把需要放入到word裡邊的資料都放到集合中并傳回,圖檔需要轉換成BASE64格式的字元串

        String imgPath_CBQS = MakeImages(map_CBQS, "line", parm, queryType, request);

        return datas;

}

//生成圖表的json格式檔案

public String MakeImages(List<Map<String,Object>> map, String type, Map<String,Object> parm, String queryType, HttpServletRequest request){

        GsonOption option = new GsonOption();

        String[] arrAxis;

        if(type.equals("line")) {//折線圖

            Line line = new Line();

            CategoryAxis  category = new CategoryAxis(); //軸分類

            if(queryType.equals("day")) {

                arrAxis = new String[24];

                for(int a = 0; a < 24; a++) {

                    String axis = StringUtils.leftPad(a + "", 2, "0");

                    arrAxis[a] = axis + ":00";

                    String value = "0";

                    for (Map<String, Object> data : map) {

                        if(axis.equals((data.get("sj") + ""))){

                            value = data.get("count") + "";

                        }

                    }

                    line.data(value);

                }

                category.data(arrAxis);

            }

            else if(queryType.equals("week") || queryType.equals("month")) {

                String startTime = parm.get("startTime") + "";

                String endTime = parm.get("endTime") + "";

                Date startDate = new Date();

                Date endDate = new Date();    

                SimpleDateFormat sdfa = new SimpleDateFormat("yyyy-MM-dd");

                SimpleDateFormat sdf2 = new SimpleDateFormat("MM月dd日");

                try {

                    if(startTime.length()>0) {

                        startDate = sdfa.parse(startTime);

                    }

                    if(endTime.length()>0) {

                        endDate = sdfa.parse(endTime);

                    }

                    Date tmp = startDate;

                    Calendar dd = Calendar.getInstance();

                    dd.setTime(startDate);

                    int days = WordGeneratorUtils.getDaysOfMonth(startDate);

                    int aLength = queryType.equals("week") ? 7 : days;

                    arrAxis = new String[aLength];

                    int i = 0;

                    do {

                        tmp = dd.getTime();

                        String axis = sdf2.format(tmp) + "";

                        String value = "0";

                        arrAxis[i] = axis;

                        for (Map<String, Object> data : map) {

                            if(axis.equals((data.get("sj") + ""))){

                                value = data.get("count") + "";

                                break;

                            }

                        }

                        line.data(value);

                        // 天數加上1

                        dd.add(Calendar.DAY_OF_MONTH, 1);

                        i++;

                    } while (tmp.getTime() < endDate.getTime());

                    category.data(arrAxis);

                }

                catch(Exception ex) {

                }

            }

            category.boundaryGap(false);//起始和結束兩端空白政策

            option.series(line);

            option.xAxis(category);//x軸

            option.yAxis(new ValueAxis());

        }

        else if(type.equals("bar")) {//柱狀圖

            Bar bar = new Bar();

            CategoryAxis  category = new CategoryAxis(); //軸分類

            arrAxis = new String[legend.size()];

            int i = 0;

            for(String s : legend) {

                String axis = s;

                arrAxis[i] = axis;

                Map<String,Object> item = new HashMap<>();

                item.put("name", s);

                String value = "0";

                for (Map<String, Object> data : map) {

                    if(s.equals(data.get("category"))) {

                        value = data.get("count") + "";

                    }

                }

                item.put("value", value);

                bar.data(item);

                i++;

            }

            //5.設定顯示工具

            option.tooltip().show(true).

                    formatter("{a}</br>{b}:{c}");//設定顯示的格式 當滑鼠放到柱狀圖上時的顯示格式

            category.data(arrAxis);

            //category.boundaryGap(false);//起始和結束兩端空白政策

            option.series(bar);

            option.xAxis(category);//x軸

            option.yAxis(new ValueAxis());

        }

        else if(type.equals("pie")) {//餅圖

            Pie pie = new Pie();//建立餅圖對象

            String[] searchs = {"正面", "負面", "中立"};

            int i = 0;

            for (Map<String, Object> data : map) {

                Map<String,Object> item = new HashMap<>();

                item.put("value",data.get("count"));

                item.put("name",data.get("sentiment"));

                pie.data(item);

                searchs[i] = data.get("sentiment") + "";

                i++;

            }

            //設定工具欄 展示  能标記

            option.toolbox().show(true).feature(Tool.mark);

            //設定圖例  圖例位置  圖例對齊方式 豎列對齊

            option.legend().data(searchs).x("right").orient(Orient.vertical);

            option.series(pie);

        }

        String json = new Gson().toJson(option);

        String fileDate = parm.get("fileDate") + "";

        Map<String,Object> resultMap=new HashMap<>();

        return generateEChart(json, resultMap, fileDate, type, request);

    }

private static final String JSpath = "C:\\echarts\\echarts-convert\\echarts-convert1.js";

    private static final Logger logger = Logger.getLogger(ReportContentRequest.class);

    public static String generateEChart(String options, Map<String,Object> resultMap, String date, String type, HttpServletRequest request) {

        String dataPath = writeFile(options, request);

        String fileName= type + date + ".png";

        String serverPath = request.getServletContext().getRealPath("/");

        //String path = "C:/echarts/test/" +fileName;//   /template/images/

        String path = request.getServletContext().getRealPath("/") + "/template/images/" + fileName;

        try {

            File file = new File(path);     //檔案路徑(路徑+檔案名)

            if (!file.exists()) {   //檔案不存在則建立檔案,先建立目錄

                File dir = new File(file.getParent());

                dir.mkdirs();

                file.createNewFile();

            }

            String cmd = "phantomjs " + JSpath + " -infile " + dataPath + " -outfile " + path;

            Process process = Runtime.getRuntime().exec(cmd);

            BufferedReader input = new BufferedReader(new InputStreamReader(process.getInputStream(), "UTF-8"));

            String line = "";

            while ((line = input.readLine()) != null) {

                logger.info(line);

            }

            input.close();

            //是否删除json資料?

        } catch (IOException e) {

            e.printStackTrace();

        } 

        return path;

    }

    public static String writeFile(String options, HttpServletRequest request) {

        String dataPath = request.getServletContext().getRealPath("/") + "/template/json/" 

                            + UUID.randomUUID().toString().substring(0, 8) +".json";

        try {

            File writename = new File(dataPath); // 相對路徑,如果沒有則要建立一個新的output.txt檔案

            if (!writename.exists()) {   //檔案不存在則建立檔案,先建立目錄

                File dir = new File(writename.getParent());

                dir.mkdirs();

                writename.createNewFile(); // 建立新檔案

            }

            BufferedWriter out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(writename), "UTF-8"));

            out.write(options); // \r\n即為換行

            out.flush(); // 把緩存區内容壓入檔案

            out.close(); // 最後記得關閉檔案

        } catch (IOException e) {

            e.printStackTrace();

        }

        return dataPath;

    }

圖檔轉Base64格式的方法

 public static String ImageToBase64(String imgPath) {

        InputStream in = null;

        byte[] data = null;

        try {

            in = new FileInputStream(imgPath);

            data = new byte[in.available()];

            in.read(data);

            in.close();

        } catch(Exception ex) {

            ex.printStackTrace();

        }

        Base64Encoder encoder = new Base64Encoder();

        return encoder.encode(data);

    }

Base64Encoder如果報錯,就項目名右鍵,buildpath,選擇JRE System Library 選中Access rules 點選Edit ,如圖

Java 使用freemaker導出word(帶echarts圖檔和表格)

public class WordGeneratorUtils {

    private static Configuration configuration = null;

    private static Map<String, Template> allTemplates = null;

    private static class FreemarkerTemplate {

        public static final String POVERTY = "template_RB";

        public static final String POVERTY_ZB = "template_ZB";

        public static final String POVERTY_YB = "template_YB";

    }

    static {

        configuration = new Configuration(Configuration.VERSION_2_3_28);

        configuration.setDefaultEncoding("utf-8");

        configuration.setClassForTemplateLoading(WordGeneratorUtils.class, "/template");//存放模闆的路徑,在項目名/src下,template為包名稱

        allTemplates = new HashMap();

        try {

            allTemplates.put(FreemarkerTemplate.POVERTY, configuration.getTemplate(FreemarkerTemplate.POVERTY + ".ftl"));

        } catch (IOException e) {

            e.printStackTrace();

            throw new RuntimeException(e);

        }

    }

}

 public static File createDoc(Map<String, Object> dataMap, Map<String, Object> parm, HttpServletRequest request) {

        try {

            int max=1000000000,min=1;

            int ran2 = (int) (Math.random()*(max-min)+min); 

            String serverPath = request.getServletContext().getRealPath("/");

            String name = "";//   /template/word/

            String queryType = parm.get("queryKey") + "";

            Template t = null;

            if(queryType.equals("day")) {

                name = serverPath + "/template/word/Report_RB" + parm.get("fileDate") + ran2 + ".doc";

                //name = "F:/Report_RB" + parm.get("fileDate") + ran2 + ".doc";

                t = allTemplates.get(FreemarkerTemplate.POVERTY);

            }

            File f = new File(name);

            //t = allTemplates.get(FreemarkerTemplate.POVERTY);

            // 這個地方不能使用FileWriter因為需要指定編碼類型否則生成的Word文檔會因為有無法識别的編碼而無法打開

            Writer w = new OutputStreamWriter(new FileOutputStream(f), "utf-8");

            t.process(dataMap, w);

            w.close();

            return f;

        } catch (Exception ex) {

            ex.printStackTrace();

            throw new RuntimeException("生成word文檔失敗");

        }

    }

OK,利用freemaker導出到word就完成啦!

繼續閱讀