Java 使用freemaker导出word(带echarts图片和表格)

时间:2024-05-18 21:48:28

一.导入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 {
            /* 写入Txt文件 */
            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就完成啦!