Echarts图形写入word模板

java后台生成统计报告word

技术方案:通过生成echart所需的json格式,调用cmd命令 phantomjs 生成统计图片,用dom4j的方式插入到word中

话不多说,直接看demo

package com.goodteacher.echart;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.UUID;

import org.apache.poi.util.IOUtils;
import org.docx4j.TraversalUtil;
import org.docx4j.dml.wordprocessingDrawing.Inline;
import org.docx4j.finders.RangeFinder;
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
import org.docx4j.openpackaging.parts.WordprocessingML.BinaryPartAbstractImage;
import org.docx4j.openpackaging.parts.WordprocessingML.MainDocumentPart;
import org.docx4j.wml.Body;
import org.docx4j.wml.CTBookmark;
import org.docx4j.wml.Document;
import org.docx4j.wml.Drawing;
import org.docx4j.wml.ObjectFactory;
import org.docx4j.wml.P;
import org.docx4j.wml.R;

import com.github.abel533.echarts.axis.CategoryAxis;
import com.github.abel533.echarts.axis.ValueAxis;
import com.github.abel533.echarts.code.Tool;
import com.github.abel533.echarts.code.Trigger;
import com.github.abel533.echarts.json.GsonOption;
import com.github.abel533.echarts.series.Line;
import com.google.gson.Gson;


public class EchartGenerate {

    
    private static final String JSpath = "C:\\Users\\mayn\\Desktop\\echart-java\\echarts-convert\\echarts-convert.js";
    
    public static void main(String[] args) throws Exception {
        
        //生成图形所需json
        //String optiona = generateLine();
        
        String optiona = "{\"title\":{\"text\":\"电流图\",\"subtext\":\"电流图\",\"x\":\"left\"},\"toolbox\":{\"feature\":{\"saveAsImage\":{\"show\":true,\"title\":\"保存为图片\",\"type\":\"png\",\"lang\":[\"点击保存\"]}},\"show\":true},\"tooltip\":{\"trigger\":\"axis\"},\"legend\":{\"data\":[\"邮件营销\",\"联盟广告\",\"视频广告\"]},\"xAxis\":[{\"type\":\"category\",\"boundaryGap\":false,\"data\":[\"周一\",\"周二\",\"周三\",\"周四\",\"周五\",\"周六\",\"周日\"]}],\"yAxis\":[{\"type\":\"value\"}],\"series\":[{\"name\":\"邮件营销\",\"type\":\"line\",\"stack\":\"总量\",\"data\":[120,132,101,134,90,230,210]},{\"name\":\"联盟广告\",\"type\":\"line\",\"stack\":\"总量\",\"data\":[220,182,191,234,290,330,310]},{\"name\":\"视频广告\",\"type\":\"line\",\"stack\":\"总量\",\"data\":[150,232,201,154,190,330,410]}]}";
        String imagePath = generateEChart(optiona);
        
        System.out.println("统计图:&&&&" + imagePath);
        
        String newWordPath = createWord(imagePath);
        
        System.out.println("生成的word文件:******" + newWordPath);

    }
    
    
    /**
     * 折线图
     *
     *  isHorizontal 是否水平放置
     */
    public static String generateLine() {
        String[] types = {"邮件营销", "联盟广告", "视频广告"};
        int[][] datas = {{120, 132, 101, 134, 90, 230, 210}, {220, 182, 191, 234, 290, 330, 310}, {150, 232, 201, 154, 190, 330, 410}};
        String title = "电流图";
        String[] valXis = {"周一", "周二", "周三", "周四", "周五", "周六", "周日"};
        GsonOption option = new GsonOption();

        option.title().text(title).subtext("电流图").x("left");// 大标题、小标题、位置

        // 提示工具
        option.tooltip().trigger(Trigger.axis);// 在轴上触发提示数据
        // 工具栏
        option.toolbox().show(true).feature(Tool.saveAsImage);// 显示保存为图片

        option.legend(types);// 图例

        CategoryAxis category = new CategoryAxis();// 轴分类
        category.data(valXis);
        category.boundaryGap(false);// 起始和结束两端空白策略

        // 循环数据
        for (int i = 0; i < types.length; i++) {
            Line line = new Line();// 三条线,三个对象
            String type = types[i];
            line.name(type).stack("总量");
            for (int j = 0; j < datas[i].length; j++)
                line.data(datas[i][j]);
            option.series(line);
        }
        option.xAxis(category);// x轴
        option.yAxis(new ValueAxis());// y轴
        return new Gson().toJson(option);
    }

    @SuppressWarnings("deprecation")
    public static String createWord(String imagePath) throws Exception {

        // 模板文件路径
        String templatePath = "D:/temp/Echart/template.docx";
        // 生成的文件路径
        String targetPath = "D:/temp/Echart/target.docx";
        // 书签名
        String bookmarkName = "bookmark";
        // 图片路径
        //String imagePath = "image.jpg";
        
        // 载入模板文件
        WordprocessingMLPackage wPackage = WordprocessingMLPackage.load(new FileInputStream(templatePath));
        // 提取正文
        MainDocumentPart mainDocumentPart = wPackage.getMainDocumentPart();
        Document wmlDoc = (Document) mainDocumentPart.getJaxbElement();
        Body body = wmlDoc.getBody();
        // 提取正文中所有段落
        List<Object> paragraphs = body.getContent();
        // 提取书签并创建书签的游标
        RangeFinder rt = new RangeFinder("CTBookmark", "CTMarkupRange");
        new TraversalUtil(paragraphs, rt);
        
        // 遍历书签
        for (CTBookmark bm:rt.getStarts()) {
            // 这儿可以对单个书签进行操作,也可以用一个map对所有的书签进行处理
            if (bm.getName().equals(bookmarkName)){             
                // 读入图片并转化为字节数组,因为docx4j只能字节数组的方式插入图片
                InputStream is = new FileInputStream(imagePath);
                byte[] bytes = IOUtils.toByteArray(is);
                // 穿件一个行内图片
                BinaryPartAbstractImage imagePart = BinaryPartAbstractImage.createImagePart(wPackage, bytes);
                 // 最后一个是限制图片的宽度,缩放的依据
                Inline inline = imagePart.createImageInline(null, null, 0,1, false, 10000);
                // 获取该书签的父级段落
                P p = (P)(bm.getParent());
                ObjectFactory factory = new ObjectFactory();
                // R对象是匿名的复杂类型,然而我并不知道具体啥意思,估计这个要好好去看看ooxml才知道
                R run = factory.createR();
                // drawing理解为画布?
                Drawing drawing = factory.createDrawing();
                drawing.getAnchorOrInline().add(inline);
                run.getContent().add(drawing);
                p.getContent().add(run);
            }
        }
        wPackage.save(new FileOutputStream(targetPath));
        return targetPath;
    }
    

    @SuppressWarnings("finally")
    public static String generateEChart(String options) {
        String dataPath = writeFile(options);
        String fileName= "test-"+UUID.randomUUID().toString().substring(0, 8) + ".png";
        String path = "D:\\temp\\Echart\\" +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;
            Runtime.getRuntime().exec(cmd);//生成图片
            /*Process process = Runtime.getRuntime().exec(cmd);
            BufferedReader input = new BufferedReader(new InputStreamReader(process.getInputStream()));
            String line = "";
            while ((line = input.readLine()) != null) {
                System.out.println(line);
            }
            input.close();*/
        } catch (IOException e) {
            e.printStackTrace();
        }finally{
             return path;
        }
    }

    public static String writeFile(String options) {
        String dataPath="D:\\chartData\\data"+ 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 FileWriter(writename));
            out.write(options); // \r\n即为换行
            out.flush(); // 把缓存区内容压入文件
            out.close(); // 最后记得关闭文件
        } catch (IOException e) {
            e.printStackTrace();
        }
        return dataPath;
    }
}
 

所需jar maven

<dependency>
            <groupId>org.docx4j</groupId>
            <artifactId>docx4j</artifactId>
            <version>3.3.1</version>
        </dependency>
            <dependency>
            <groupId>com.github.abel533</groupId>
            <artifactId>ECharts</artifactId>
            <version>3.0.0.2</version>
        </dependency>

<dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-excelant</artifactId>
            <version>3.12</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-scratchpad</artifactId>
            <version>3.12</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>3.8</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml-schemas</artifactId>
            <version>3.8</version>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-exec</artifactId>
            <version>1.3</version>
        </dependency>
        <dependency>
            <groupId>com.google.code.gson</groupId>
            <artifactId>gson</artifactId>
        </dependency>

好!

以上,完美解决、

猜你喜欢

转载自blog.csdn.net/yangkqandy/article/details/89419989