精华内容
下载资源
问答
  • 整理数据和图表,导入到一份规范化的word中 准备工作 需求并不是很明确,就先实现word导出,我采用的是freemarker 首先:搭建一个boot项目 添加pom中的包 <!--web模块用作测试请求--> <...
    • 功能介绍

    1. 需求由来

           整理数据和图表,导入到一份规范化的word中

    1. 准备工作

          需求并不是很明确,就先实现word导出,我采用的是freemarker

          首先:搭建一个boot项目 

          添加pom中的包

       <!--web模块用作测试请求-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
     <!-- freemarker 模版引擎 -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-freemarker</artifactId>
            </dependency>
      <!-- fastjson-->
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>fastjson</artifactId>
                <version>1.2.44</version>
            </dependency>
          <!--thymeleaf,方便页面数据传输-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-thymeleaf</artifactId>
            </dependency>
     <!--jquery-->
            <dependency>
                <groupId>org.webjars</groupId>
                <artifactId>jquery</artifactId>
                <version>3.4.0</version>
            </dependency>

       创建word模板

       记得一定要用office,不然导出的word可能会出现损坏

        接着在word中输入一些信息,如文字,表格等

       

       将文件另存为xml格式,最好是word2003的xml这样,高版本低配低版本的特性,保证下载下来的word都能用

      保存后用记事本打开这个xml文件,复制出来,去网上随便找个网站吧xml格式化一下,这样方便我们去阅读

    我这里经常用格式化的在线网址:http://www.bejson.com/otherformat/xml/

    在项目中创建一个.ftl结尾的文件,将刚刚格式化好的xml复制进去

    创建一个Controller方法,方便外部访问,这是测试方法

        private final ExportUtil exportUtil;
        @Autowired
        public WordController(ExportUtil exportUtil) {
            this.exportUtil = exportUtil;
        }
    
        @RequestMapping(value = "/wordDownload")
        public void wordDownload(HttpServletRequest request, HttpServletResponse response) throws IOException {
            Map<String, Object> map=new HashMap<>();
            map.put("title","hello ! ! 我是一个标题");
            List<Map<String, Object>> excelInfo=new ArrayList<>();
            for (int i=0;i<3;i++){
                Map<String, Object> info=new HashMap<>();
                info.put("name","张"+i);
                info.put("info","我是第"+i+"个介绍");
                excelInfo.add(info);
            }
            map.put("excelInfo",excelInfo);
            exportUtil.exportTemplateWord(response,request,map,"测试","word/Template.ftl");
        }
    

    基于freemarker工具类exportUtil

    package com.qxl.wordexport.util;
    
    import freemarker.template.Configuration;
    import freemarker.template.Template;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Component;
    import org.springframework.util.StringUtils;
    
    import javax.servlet.ServletOutputStream;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.*;
    import java.net.URLEncoder;
    import java.time.LocalDateTime;
    import java.util.Map;
    
    /**
     * @program: hotline
     * @author: Fulin
     * @create: 2018-12-10 17:59
     **/
    @Component
    public class ExportUtil {
    
        private static final String ENCODING = "utf-8";
        private static final String WORD_CONTENTTYPE = "application/msword";
    
        private static final String EXCEL_CONTENTTYPE = "application/x-download";
    
    
        //    private static final String BASE_PATH = ClassUtils.getDefaultClassLoader().getResourceAsStream()
        private static final String TEMPLATEFOLDER = BASE_PATH + File.separator + "templates";
    //    private static final String TEMPLATEFOLDER = BASE_PATH;
    
      /*  private static Configuration configuration;
    
        static {
            configuration = new Configuration(Configuration.VERSION_2_3_28);
            configuration.setDefaultEncoding("utf-8");
            try {
                configuration.setDirectoryForTemplateLoading(new File("/word"));
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    */
        private final Configuration configuration; //freeMarker configuration
    
        @Autowired
        public ExportUtil(Configuration configuration) {
            this.configuration = configuration;
        }
    
    
        /**
         * freemarker模版导出word
         *
         * @param response 响应
         * @param map      数据
         * @param title    标题
         * @param ftlFile  文件路径 templates 目录下的
         * @throws IOException IO异常
         */
        public  void exportTemplateWord(HttpServletResponse response, HttpServletRequest request, Map map, String title, String ftlFile) throws IOException {
            Template freemarkerTemplate = configuration.getTemplate(ftlFile);
            File file;
            String fileName = title+LocalDateTime.now().toString() + ".doc";
            if (!StringUtils.isEmpty(title)) {
                fileName = title + ".doc";
                if (isIE(request)) {
                    fileName = URLEncoder.encode(fileName, "UTF8");
                } else {
                    fileName = new String(fileName.getBytes("UTF-8"), "ISO-8859-1");
                }
            }
            response.setCharacterEncoding("utf-8");
            response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
            response.setContentType(WORD_CONTENTTYPE);
            response.setCharacterEncoding(ENCODING);
            file = createDoc(map, freemarkerTemplate);
            //java7的新回收特性
            tempBuffer(response, file);
        }
    
        /**
         * freemarker模版导出excel
         *
         * @param response 响应
         * @param map      数据
         * @param title    标题
         * @param ftlFile  文件路径 templates 目录下的
         * @throws IOException IO异常
         */
        public  void exportTemplateExcel(HttpServletResponse response, Map map, String title, String ftlFile) throws IOException {
            Template freemarkerTemplate = configuration.getTemplate(ftlFile);
            File file;
            String fileName = title + LocalDateTime.now().toString() + ".xls";
            response.setHeader("Content-Disposition", "attachment;filename="
                    .concat(String.valueOf(URLEncoder.encode(fileName, ENCODING))));
            response.setContentType(EXCEL_CONTENTTYPE);
            response.setCharacterEncoding(ENCODING);
            file = createDoc(map, freemarkerTemplate);
            tempBuffer(response, file);
        }
    
        private static void tempBuffer(HttpServletResponse response, File file) throws IOException {
            //java7的新回收特性
            try (InputStream fin = new FileInputStream(file); ServletOutputStream out = response.getOutputStream()) {
                // 调用工具类的createDoc方法生成Word文档
                // 设置浏览器以下载的方式处理该文件名
                byte[] buffer = new byte[1024];  // 缓冲区
                int bytesToRead = -1;
                // 通过循环将读入的Word文件的内容输出到浏览器中
                while ((bytesToRead = fin.read(buffer)) != -1) {
                    out.write(buffer, 0, bytesToRead);
                }
            } finally {
                if (file != null) {
                    boolean delete = file.delete();
                }
            }
        }
    
        private static File createDoc(Map<?, ?> dataMap, Template template) {
            String name = "temp";
            File f = new File(name);
            try {
                //这个地方不能使用FileWriter因为需要指定编码类型否则生成的Word文档会因为有无法识别的编码而无法打开
                Writer w = new OutputStreamWriter(new FileOutputStream(f), ENCODING);
                template.process(dataMap, w);
                w.close();
            } catch (Exception ex) {
                ex.printStackTrace();
                throw new RuntimeException(ex);
            }
            return f;
        }
    
        private static boolean isIE(HttpServletRequest request) {
            return request.getHeader("USER-AGENT").toLowerCase().indexOf("msie") > 0 || request.getHeader("USER-AGENT").toLowerCase().indexOf("rv:11.0") > 0 || request.getHeader("USER-AGENT").toLowerCase().indexOf("edge") > 0;
        }
    
    }
    

    接着将map中的数据填充在word模板中,打开之前创建的  .ftl   结尾的文件,找到正文

    将这个文字替换成freemarker的表达式,取出我们的传进来数据

    访问我们项目路径:http://127.0.0.1:8080/wordDownload

    文件下载完毕,打开发现我们后台传过去标题也在上面了

    导出word功能已经完成,接着进行其他功能的实现

     

    • 开始制作

        制作word模板

          创建word文档,记得一定要用office

    另存为2003xml,后记事本打开,粘贴格式化后,项目中创建   .ftl    结尾文件,把格式化好的xml文件放进   .ftl 文件中

    <w:binData>中存放的是图片的base64编码,我们可以把他粘贴出来去在线解析网站中看一下是不是我们之前放的图片

     

    我常用在线解析网站:http://imgbase64.duoshitong.com/

    在这需要加上前缀   data:image/png;base64,      后面跟上<w:binData>标签内的字符串,效果如下

    这么说,我们只需要将往ftl文件对应的<w:binData>标签中放入图片的base64编码就可以,于是我开始想办法去获取图表的base64编码

      1.试用echarts

    echarts在平时用的比较多,所以打算先用echarts实现,先去官网找相关的js和文档,通过文档我们找到了这样一个方法,可以直接获取图表的base64编码,但是有一点需要注意,就是图表需要去除动画效果,不然无法获取   去除方法为        animation:false

    下面粘贴一下我测试页面代码,我在控制到打印一下我想要的信息

    <!DOCTYPE html>
    <html lang="en" xmlns:th="http://www.springframework.org/schema/mvc">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <script th:src="@{/echarts/echarts.min.js}"></script>
        <script th:src="@{/webjars/jquery/3.4.0/jquery.js}"></script>
    </head>
    <body>
    <div id="myChart" style="width: 600px;height:600px;"></div>
    <script type="text/javascript">
        $(function () {
            echartsDemo();
        });
    
        function echartsDemo() {
            var myChart = echarts.init(document.getElementById("myChart"));
            option = {
                title : {
                    text: '某站点用户访问来源',
                    subtext: '纯属虚构',
                    x:'center'
                },
                tooltip : {
                    trigger: 'item',
                    formatter: "{a} <br/>{b} : {c} ({d}%)"
                },
                legend: {
                    orient: 'vertical',
                    left: 'left',
                    data: ['直接访问','邮件营销','联盟广告','视频广告','搜索引擎']
                },
                series : [
                    {
                        name: '访问来源',
                        type: 'pie',
                        radius : '75%',
                        center: ['50%', '50%'],
                        data:[
                            {value:335, name:'直接访问'},
                            {value:310, name:'邮件营销'},
                            {value:234, name:'联盟广告'},
                            {value:135, name:'视频广告'},
                            {value:1548, name:'搜索引擎'}
                        ],
                        itemStyle: {
                            emphasis: {
                                shadowBlur: 10,
                                shadowOffsetX: 0,
                                shadowColor: 'rgba(0, 0, 0, 0.5)'
                            }
                        }
                    }
                ],
                animation:false
            };
            myChart.setOption(option);
            var imgData = myChart.getConnectedDataURL();
            console.log(imgData);
        }
    </script>
    </body>
    </html>

    拿到生成的base64编码,去看一下对不对

    粘贴后,放入之前转码网站,发现没问题,现在只需要把这段base64编码提交到后台,放入ftl模板中,我们的word导出功能就做完了

     

    功能都实现了,那么是不是就结束了呢,不,这只是刚刚开始,由于任务布置的时候只是让实现功能,布置任务的人给我说,项目中的图表是用highcharts

        2.试用highcharts

    第一次用highcharts,我就去官网看了半天,发现只有一个图片下载的方法,但是这个图片我是拿不到的,我只能换一种思路,用外部的插件,去网上找了半天最后选取了 canvg.js,还有一种是html2canvas.min.js,这里我介绍canvg.js的实现,如果有兴趣可以自己研究一下另外一种,下面是他的前段代码

    <!DOCTYPE html>
    <html lang="en" xmlns:th="http://www.thymeleaf.org">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <script th:src="@{/webjars/jquery/3.4.0/jquery.js}"></script>
        <script th:src="@{/highcharts/highcharts.js}"></script>
        <script th:src="@{/highcharts/exporting.js}"></script>
        <script th:src="@{/canvg/canvg.js}"></script>
    </head>
    <body>
    <h1>首页</h1>
    
    <div id="hightCharts"></div>
    
    <canvas id="canvasId" style="display: none"></canvas>
    
    <script type="text/javascript">
    
        Highcharts.chart('hightCharts', {
            chart: {
                plotBackgroundColor: null,
                plotBorderWidth: null,
                plotShadow: false,
                type: 'pie'
            },
            title: {
                text: '2018年1月浏览器市场份额'
            },
            tooltip: {
                pointFormat: '{series.name}: <b>{point.percentage:.1f}%</b>'
            },
            plotOptions: {
                pie: {
                    allowPointSelect: true,
                    cursor: 'pointer',
                    dataLabels: {
                        enabled: true,
                        format: '<b>{point.name}</b>: {point.percentage:.1f} %',
                        style: {
                            color: (Highcharts.theme && Highcharts.theme.contrastTextColor) || 'black'
                        }
                    }
                }
            },
            series: [{
                name: 'Brands',
                colorByPoint: true,
                data: [{
                    name: 'Chrome',
                    y: 61.41,
                    sliced: true,
                    selected: true
                }, {
                    name: 'Internet Explorer',
                    y: 11.84
                }, {
                    name: 'Firefox',
                    y: 10.85
                }, {
                    name: 'Edge',
                    y: 4.67
                }, {
                    name: 'Safari',
                    y: 4.18
                }, {
                    name: 'Sogou Explorer',
                    y: 1.64
                }, {
                    name: 'Opera',
                    y: 1.6
                }, {
                    name: 'QQ',
                    y: 1.2
                }, {
                    name: 'Other',
                    y: 2.61
                }]
            }]
        });
        var chartData = $("#hightCharts").highcharts().getSVG();
        canvg(canvasId,chartData);
        function convertCanvas(canvas) {
            var image = new Image();
            image.src = canvas.toDataURL("image/png");
            return image
        }
        var canvas = document.createElement('canvasId');
        var imageData = convertCanvas(canvasId).src;
        console.log(imageData);
    
    </script>
    </body>
    </html>

    在控制台上拿到打印的信息,放到在线解码网站,图片生成成功,另外我这找到另外一种后台的生成方法,挺好用的,但是如果生成多张图片,可能会比较麻烦,因为这篇文章中把前台单独生成了一个项目,以请求的方式拿到图片,这是链接

    弄了这么多感觉已经到了尾声,终于,我拿到了项目!发现项目里压根没有highcharts,但是我找到了amchart(此处应有黑人感叹号!!!),这是什么鬼,我一搞后台的,用了这么多前台的插件,但是还没完成?!算了,继续看amchart吧

        3.试用amchart

    心平气和去amchart官网翻文档,中间踩的坑就不多说了,下面是官方文档给的方法

    接着是我的前段代码

    <!DOCTYPE html>
    <html lang="en" xmlns:th="http://www.thymeleaf.org">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <script th:src="@{/webjars/jquery/3.4.0/jquery.js}"></script>
        <!-- Resources -->
        <script src="https://www.amcharts.com/lib/4/core.js"></script>
        <script th:src="@{/amcharts/charts.js}"></script>
    </head>
    <body>
    <h1>首页</h1>
        <!-- HTML -->
        <div id="chartdiv" style="width: 100%;height: 500px"></div>
    
    <script type="text/javascript">
            $(function () {
                aaa();
            });
            function aaa() {
                var chart = am4core.create("chartdiv", am4charts.PieChart);
                chart.data = [ {
                    "country": "Lithuania",
                    "litres": 501.9
                }, {
                    "country": "Czech Republic",
                    "litres": 301.9
                }, {
                    "country": "Ireland",
                    "litres": 201.1
                }, {
                    "country": "Germany",
                    "litres": 165.8
                }, {
                    "country": "Australia",
                    "litres": 139.9
                }, {
                    "country": "Austria",
                    "litres": 128.3
                }, {
                    "country": "UK",
                    "litres": 99
                }, {
                    "country": "Belgium",
                    "litres": 60
                }, {
                    "country": "The Netherlands",
                    "litres": 50
                } ];
                var pieSeries = chart.series.push(new am4charts.PieSeries());
                pieSeries.dataFields.value = "litres";
                pieSeries.dataFields.category = "country";
                chart.exporting.getImage("png").then(function(imgData) {
                    console.log(imgData);
                });
    
            }
    
    </script>
    </body>
    </html>

    控制台拿到打印信息,没问题

        4.坑爹的IE7

    这回总可以了吧,欣喜的跑起项目,看着项目再跑,总觉得事情没有这么简单,果然Chrome不兼容,赶紧过去问了一下,适用于IE,并且还要是兼容模式,赶紧打开IE调试兼容模式,看到默认是IE7,心里已经凉了半截,因为这几个图表只能适用于IE9+,我试试看调高一点的版本,结果凉凉,突然想到项目里用的是amchart,那么我amchart一定是能用的,兴奋赶紧去尝试一下,发现项目中amchart是老版本,新版本的方法不兼容,凉透了,脑中灵光一现,不是还有一个html2canvas.js嘛,麻溜的就去官网看,结果发现,最低适配到IE9,这可咋整,难道天要亡我?不行不行,我又去任务发布人哪里问了一下,能不能不用amchart,因为我实现不了,他说可以呀,只要基础的饼图,柱状图,折线图有就行,别太丑美观一点的。之前朋友说有java纯后台生成的图表,我网上了解了一下,有个jfreechart的,感觉可以试试.....

        5.jfreechart

    已经到这个时候了,没有退路了,硬着头皮试试呗,看了几篇博客,总结了一下,发现挺简单的,用的pom包

    <!--jfreechart-->
    <dependency>
        <groupId>jfree</groupId>
        <artifactId>jfreechart</artifactId>
        <version>1.0.13</version>
    </dependency>

    借鉴别人优化的图表样式

    package com.qxl.wordexport.util;
    
    import com.qxl.wordexport.entity.Serie;
    import org.jfree.chart.ChartFactory;
    import org.jfree.chart.JFreeChart;
    import org.jfree.chart.StandardChartTheme;
    import org.jfree.chart.axis.DateAxis;
    import org.jfree.chart.axis.DateTickUnit;
    import org.jfree.chart.axis.DateTickUnitType;
    import org.jfree.chart.axis.ValueAxis;
    import org.jfree.chart.block.BlockBorder;
    import org.jfree.chart.labels.*;
    import org.jfree.chart.plot.*;
    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.chart.renderer.xy.StandardXYBarPainter;
    import org.jfree.chart.renderer.xy.XYBarRenderer;
    import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
    import org.jfree.data.category.DefaultCategoryDataset;
    import org.jfree.data.general.DefaultPieDataset;
    import org.jfree.data.time.Day;
    import org.jfree.data.time.TimeSeries;
    import org.jfree.ui.RectangleInsets;
    import org.jfree.ui.TextAnchor;
    
    import java.awt.*;
    import java.text.DecimalFormat;
    import java.text.NumberFormat;
    import java.text.ParseException;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    import java.util.Vector;
    
    /**
     * Jfreechart工具类
     * <p>
     * 解决中午乱码问题<br>
     * 用来创建类别图表数据集、创建饼图数据集、时间序列图数据集<br>
     * 用来对柱状图、折线图、饼图、堆积柱状图、时间序列图的样式进行渲染<br>
     * 设置X-Y坐标轴样式
     * <p>
     * 引自文章:https://www.liangzl.com/get-article-detail-26733.html
     *
     */
    
    public class JfreeChartStyle {
        private static String NO_DATA_MSG = "数据加载失败";
        private static Font FONT = new Font("宋体", Font.PLAIN, 12);
        public static Color[] CHART_COLORS = {
                new Color(31,129,188), new Color(92,92,97), new Color(144,237,125), new Color(255,188,117),
                new Color(153,158,255), new Color(255,117,153), new Color(253,236,109), new Color(128,133,232),
                new Color(158,90,102),new Color(255, 204, 102) };// 颜色
    
        static {
            setChartTheme();
        }
    
        public JfreeChartStyle() {
        }
    
        /**
         * 中文主题样式 解决乱码
         */
        public static void setChartTheme() {
            // 设置中文主题样式 解决乱码
            StandardChartTheme chartTheme = new StandardChartTheme("CN");
            // 设置标题字体
            chartTheme.setExtraLargeFont(FONT);
            // 设置图例的字体
            chartTheme.setRegularFont(FONT);
            // 设置轴向的字体
            chartTheme.setLargeFont(FONT);
            chartTheme.setSmallFont(FONT);
            chartTheme.setTitlePaint(new Color(51, 51, 51));
            chartTheme.setSubtitlePaint(new Color(85, 85, 85));
    
            chartTheme.setLegendBackgroundPaint(Color.WHITE);// 设置标注
            chartTheme.setLegendItemPaint(Color.BLACK);//
            chartTheme.setChartBackgroundPaint(Color.WHITE);
            // 绘制颜色绘制颜色.轮廓供应商
            // paintSequence,outlinePaintSequence,strokeSequence,outlineStrokeSequence,shapeSequence
    
            Paint[] OUTLINE_PAINT_SEQUENCE = new Paint[] { Color.WHITE };
            // 绘制器颜色源
            DefaultDrawingSupplier drawingSupplier = new DefaultDrawingSupplier(CHART_COLORS, CHART_COLORS, OUTLINE_PAINT_SEQUENCE,
                    DefaultDrawingSupplier.DEFAULT_STROKE_SEQUENCE, DefaultDrawingSupplier.DEFAULT_OUTLINE_STROKE_SEQUENCE,
                    DefaultDrawingSupplier.DEFAULT_SHAPE_SEQUENCE);
            chartTheme.setDrawingSupplier(drawingSupplier);
    
            chartTheme.setPlotBackgroundPaint(Color.WHITE);// 绘制区域
            chartTheme.setPlotOutlinePaint(Color.WHITE);// 绘制区域外边框
            chartTheme.setLabelLinkPaint(new Color(8, 55, 114));// 链接标签颜色
            chartTheme.setLabelLinkStyle(PieLabelLinkStyle.CUBIC_CURVE);
    
            chartTheme.setAxisOffset(new RectangleInsets(5, 12, 5, 12));
            chartTheme.setDomainGridlinePaint(new Color(192, 208, 224));// X坐标轴垂直网格颜色
            chartTheme.setRangeGridlinePaint(new Color(192, 192, 192));// Y坐标轴水平网格颜色
    
            chartTheme.setBaselinePaint(Color.WHITE);
            chartTheme.setCrosshairPaint(Color.BLUE);// 不确定含义
            chartTheme.setAxisLabelPaint(new Color(51, 51, 51));// 坐标轴标题文字颜色
            chartTheme.setTickLabelPaint(new Color(67, 67, 72));// 刻度数字
            chartTheme.setBarPainter(new StandardBarPainter());// 设置柱状图渲染
            chartTheme.setXYBarPainter(new StandardXYBarPainter());// XYBar 渲染
    
            chartTheme.setItemLabelPaint(Color.black);
            chartTheme.setThermometerPaint(Color.white);// 温度计
    
            ChartFactory.setChartTheme(chartTheme);
        }
    
        /**
         * 必须设置文本抗锯齿
         */
        public static void setAntiAlias(JFreeChart chart) {
            chart.setTextAntiAlias(false);
    
        }
    
        /**
         * 设置图例无边框,默认黑色边框
         */
        public static void setLegendEmptyBorder(JFreeChart chart) {
            chart.getLegend().setFrame(new BlockBorder(Color.WHITE));
    
        }
    
        /**
         * 创建类别数据集合
         */
        public static DefaultCategoryDataset createDefaultCategoryDataset(Vector<Serie> series, String[] categories) {
            DefaultCategoryDataset dataset = new DefaultCategoryDataset();
    
            for (Serie serie : series) {
                String name = serie.getName();
                Vector<Object> data = serie.getData();
                if (data != null && categories != null && data.size() == categories.length) {
                    for (int index = 0; index < data.size(); index++) {
                        String value = data.get(index) == null ? "" : data.get(index).toString();
                        if (isPercent(value)) {
                            value = value.substring(0, value.length() - 1);
                        }
                        if (isNumber(value)) {
                            dataset.setValue(Double.parseDouble(value), name, categories[index]);
                        }
                    }
                }
    
            }
            return dataset;
    
        }
    
        /**
         * 创建饼图数据集合
         */
        public static DefaultPieDataset createDefaultPieDataset(String[] categories, Object[] datas) {
            DefaultPieDataset dataset = new DefaultPieDataset();
            for (int i = 0; i < categories.length && categories != null; i++) {
                String value = datas[i].toString();
                if (isPercent(value)) {
                    value = value.substring(0, value.length() - 1);
                }
                if (isNumber(value)) {
                    dataset.setValue(categories[i], Double.valueOf(value));
                }
            }
            return dataset;
    
        }
    
        /**
         * 创建时间序列数据
         *
         * @param category
         *            类别
         * @param dateValues
         *            日期-值 数组
         * @param xAxisTitle
         *            X坐标轴标题
         * @return
         */
        public static TimeSeries createTimeseries(String category, Vector<Object[]> dateValues) {
            TimeSeries timeseries = new TimeSeries(category);
    
            if (dateValues != null) {
                SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
                for (Object[] objects : dateValues) {
                    Date date = null;
                    try {
                        date = dateFormat.parse(objects[0].toString());
                    } catch (ParseException e) {
                    }
                    String sValue = objects[1].toString();
                    double dValue = 0;
                    if (date != null && isNumber(sValue)) {
                        dValue = Double.parseDouble(sValue);
                        timeseries.add(new Day(date), dValue);
                    }
                }
            }
    
            return timeseries;
        }
    
        /**
         * 设置 折线图样式
         *
         * @param plot
         * @param isShowDataLabels
         *            是否显示数据标签 默认不显示节点形状
         */
        public static void setLineRender(CategoryPlot plot, boolean isShowDataLabels) {
            setLineRender(plot, isShowDataLabels, false);
        }
    
        /**
         * 设置折线图样式
         *
         * @param plot
         * @param isShowDataLabels
         *            是否显示数据标签
         */
        public static void setLineRender(CategoryPlot plot, boolean isShowDataLabels, boolean isShapesVisible) {
            plot.setNoDataMessage(NO_DATA_MSG);
            plot.setInsets(new RectangleInsets(10, 10, 0, 10), false);
            LineAndShapeRenderer renderer = (LineAndShapeRenderer) plot.getRenderer();
    
            renderer.setStroke(new BasicStroke(1.5F));
            if (isShowDataLabels) {
                renderer.setBaseItemLabelsVisible(true);
                renderer.setBaseItemLabelGenerator(new StandardCategoryItemLabelGenerator(StandardCategoryItemLabelGenerator.DEFAULT_LABEL_FORMAT_STRING,
                        NumberFormat.getInstance()));
                renderer.setBasePositiveItemLabelPosition(new ItemLabelPosition(ItemLabelAnchor.OUTSIDE1, TextAnchor.BOTTOM_CENTER));// weizhi
            }
            renderer.setBaseShapesVisible(isShapesVisible);// 数据点绘制形状
            setXAixs(plot);
            setYAixs(plot);
    
        }
    
        /**
         * 设置时间序列图样式
         *
         * @param plot
         * @param isShowData
         *            是否显示数据
         * @param isShapesVisible
         *            是否显示数据节点形状
         */
        public static void setTimeSeriesRender(Plot plot, boolean isShowData, boolean isShapesVisible) {
    
            XYPlot xyplot = (XYPlot) plot;
            xyplot.setNoDataMessage(NO_DATA_MSG);
            xyplot.setInsets(new RectangleInsets(10, 10, 5, 10));
    
            XYLineAndShapeRenderer xyRenderer = (XYLineAndShapeRenderer) xyplot.getRenderer();
    
            xyRenderer.setBaseItemLabelGenerator(new StandardXYItemLabelGenerator());
            xyRenderer.setBaseShapesVisible(false);
            if (isShowData) {
                xyRenderer.setBaseItemLabelsVisible(true);
                xyRenderer.setBaseItemLabelGenerator(new StandardXYItemLabelGenerator());
                xyRenderer.setBasePositiveItemLabelPosition(new ItemLabelPosition(ItemLabelAnchor.OUTSIDE1, TextAnchor.BOTTOM_CENTER));// weizhi
            }
            xyRenderer.setBaseShapesVisible(isShapesVisible);// 数据点绘制形状
    
            DateAxis domainAxis = (DateAxis) xyplot.getDomainAxis();
            domainAxis.setAutoTickUnitSelection(false);
            DateTickUnit dateTickUnit = new DateTickUnit(DateTickUnitType.YEAR, 1, new SimpleDateFormat("yyyy-MM")); // 第二个参数是时间轴间距
            domainAxis.setTickUnit(dateTickUnit);
    
            StandardXYToolTipGenerator xyTooltipGenerator = new StandardXYToolTipGenerator("{1}:{2}", new SimpleDateFormat("yyyy-MM-dd"), new DecimalFormat("0"));
            xyRenderer.setBaseToolTipGenerator(xyTooltipGenerator);
    
            setXY_XAixs(xyplot);
            setXY_YAixs(xyplot);
    
        }
    
        /**
         * 设置时间序列图样式 -默认不显示数据节点形状
         *
         * @param plot
         * @param isShowData
         *            是否显示数据
         */
    
        public static void setTimeSeriesRender(Plot plot, boolean isShowData) {
            setTimeSeriesRender(plot, isShowData, false);
        }
    
        /**
         * 设置时间序列图渲染:但是存在一个问题:如果timeseries里面的日期是按照天组织, 那么柱子的宽度会非常小,和直线一样粗细
         *
         * @param plot
         * @param isShowDataLabels
         */
    
        public static void setTimeSeriesBarRender(Plot plot, boolean isShowDataLabels) {
    
            XYPlot xyplot = (XYPlot) plot;
            xyplot.setNoDataMessage(NO_DATA_MSG);
    
            XYBarRenderer xyRenderer = new XYBarRenderer(0.1D);
            xyRenderer.setBaseItemLabelGenerator(new StandardXYItemLabelGenerator());
    
            if (isShowDataLabels) {
                xyRenderer.setBaseItemLabelsVisible(true);
                xyRenderer.setBaseItemLabelGenerator(new StandardXYItemLabelGenerator());
            }
    
            StandardXYToolTipGenerator xyTooltipGenerator = new StandardXYToolTipGenerator("{1}:{2}", new SimpleDateFormat("yyyy-MM-dd"), new DecimalFormat("0"));
            xyRenderer.setBaseToolTipGenerator(xyTooltipGenerator);
            setXY_XAixs(xyplot);
            setXY_YAixs(xyplot);
    
        }
    
        /**
         * 设置柱状图渲染
         *
         * @param plot
         * @param isShowDataLabels
         */
        public static void setBarRenderer(CategoryPlot plot, boolean isShowDataLabels) {
    
            plot.setNoDataMessage(NO_DATA_MSG);
            plot.setInsets(new RectangleInsets(10, 10, 5, 10));
            BarRenderer renderer = (BarRenderer) plot.getRenderer();
            renderer.setBaseItemLabelGenerator(new StandardCategoryItemLabelGenerator());
            renderer.setMaximumBarWidth(0.075);// 设置柱子最大宽度
    
            if (isShowDataLabels) {
                renderer.setBaseItemLabelsVisible(true);
            }
    
            setXAixs(plot);
            setYAixs(plot);
        }
    
        /**
         * 设置堆积柱状图渲染
         *
         * @param plot
         */
    
        public static void setStackBarRender(CategoryPlot plot) {
            plot.setNoDataMessage(NO_DATA_MSG);
            plot.setInsets(new RectangleInsets(10, 10, 5, 10));
            StackedBarRenderer renderer = (StackedBarRenderer) plot.getRenderer();
            renderer.setBaseItemLabelGenerator(new StandardCategoryItemLabelGenerator());
            plot.setRenderer(renderer);
            setXAixs(plot);
            setYAixs(plot);
        }
    
        /**
         * 设置类别图表(CategoryPlot) X坐标轴线条颜色和样式
         *
         * @param axis
         */
        public static void setXAixs(CategoryPlot plot) {
            Color lineColor = new Color(31, 121, 170);
            plot.getDomainAxis().setAxisLinePaint(lineColor);// X坐标轴颜色
            plot.getDomainAxis().setTickMarkPaint(lineColor);// X坐标轴标记|竖线颜色
    
        }
    
        /**
         * 设置类别图表(CategoryPlot) Y坐标轴线条颜色和样式 同时防止数据无法显示
         *
         * @param axis
         */
        public static void setYAixs(CategoryPlot plot) {
            Color lineColor = new Color(192, 208, 224);
            ValueAxis axis = plot.getRangeAxis();
            axis.setAxisLinePaint(lineColor);// Y坐标轴颜色
            axis.setTickMarkPaint(lineColor);// Y坐标轴标记|竖线颜色
            // 隐藏Y刻度
            axis.setAxisLineVisible(false);
            axis.setTickMarksVisible(false);
            // Y轴网格线条
            plot.setRangeGridlinePaint(new Color(192, 192, 192));
            plot.setRangeGridlineStroke(new BasicStroke(1));
    
            plot.getRangeAxis().setUpperMargin(0.1);// 设置顶部Y坐标轴间距,防止数据无法显示
            plot.getRangeAxis().setLowerMargin(0.1);// 设置底部Y坐标轴间距
    
        }
    
        /**
         * 设置XY图表(XYPlot) X坐标轴线条颜色和样式
         *
         * @param axis
         */
        public static void setXY_XAixs(XYPlot plot) {
            Color lineColor = new Color(31, 121, 170);
            plot.getDomainAxis().setAxisLinePaint(lineColor);// X坐标轴颜色
            plot.getDomainAxis().setTickMarkPaint(lineColor);// X坐标轴标记|竖线颜色
    
        }
    
        /**
         * 设置XY图表(XYPlot) Y坐标轴线条颜色和样式 同时防止数据无法显示
         *
         * @param axis
         */
        public static void setXY_YAixs(XYPlot plot) {
            Color lineColor = new Color(192, 208, 224);
            ValueAxis axis = plot.getRangeAxis();
            axis.setAxisLinePaint(lineColor);// X坐标轴颜色
            axis.setTickMarkPaint(lineColor);// X坐标轴标记|竖线颜色
            // 隐藏Y刻度
            axis.setAxisLineVisible(false);
            axis.setTickMarksVisible(false);
            // Y轴网格线条
            plot.setRangeGridlinePaint(new Color(192, 192, 192));
            plot.setRangeGridlineStroke(new BasicStroke(1));
            plot.setDomainGridlinesVisible(false);
    
            plot.getRangeAxis().setUpperMargin(0.12);// 设置顶部Y坐标轴间距,防止数据无法显示
            plot.getRangeAxis().setLowerMargin(0.12);// 设置底部Y坐标轴间距
    
        }
    
        /**
         * 设置饼状图渲染
         */
        public static void setPieRender(Plot plot) {
    
            plot.setNoDataMessage(NO_DATA_MSG);
            plot.setInsets(new RectangleInsets(10, 10, 5, 10));
            PiePlot piePlot = (PiePlot) plot;
            piePlot.setInsets(new RectangleInsets(0, 0, 0, 0));
            piePlot.setCircular(true);// 圆形
    
            // piePlot.setSimpleLabels(true);// 简单标签
            piePlot.setLabelGap(0.01);
            piePlot.setInteriorGap(0.05D);
            piePlot.setLegendItemShape(new Rectangle(10, 10));// 图例形状
            piePlot.setIgnoreNullValues(true);
            piePlot.setLabelBackgroundPaint(null);// 去掉背景色
            piePlot.setLabelShadowPaint(null);// 去掉阴影
            piePlot.setLabelOutlinePaint(null);// 去掉边框
            piePlot.setShadowPaint(null);
            // 0:category 1:value:2 :percentage
            piePlot.setLabelGenerator(new StandardPieSectionLabelGenerator("{0}:{2}"));// 显示标签数据
        }
    
        /**
         * 是不是一个%形式的百分比
         *
         * @param str
         * @return
         */
        public static boolean isPercent(String str) {
            return str != null ? str.endsWith("%") && isNumber(str.substring(0, str.length() - 1)) : false;
        }
    
        /**
         * 是不是一个数字
         *
         * @param str
         * @return
         */
        public static boolean isNumber(String str) {
            return str != null ? str.matches("^[-+]?(([0-9]+)((([.]{0})([0-9]*))|(([.]{1})([0-9]+))))$") : false;
        }
    
    }
    

    自己简单封装了一下饼图,柱状图和折线图的调用方法

    package com.qxl.wordexport.util;
    
    import com.qxl.wordexport.entity.Serie;
    import org.jfree.chart.ChartFactory;
    import org.jfree.chart.ChartUtilities;
    import org.jfree.chart.JFreeChart;
    import org.jfree.chart.plot.CategoryPlot;
    import org.jfree.chart.plot.PlotOrientation;
    import org.jfree.data.category.CategoryDataset;
    import org.jfree.data.general.DefaultPieDataset;
    import sun.misc.BASE64Encoder;
    
    import java.awt.*;
    import java.io.*;
    import java.util.Date;
    import java.util.Locale;
    import java.util.Vector;
    
    
    /**
     * jfreechart生成工具类
     * 生成效果:在指定目录下生成png图片,生成图片base64码
     * 可生成类型:折线图,柱状图,饼图
     */
    public class JfreeChartUtil {
    
        /**
         * 图片存储位置可以写在配置文件中
         */
        private static String  CHART_IMG_FILE="E:/boot/charts/";
    
    
        /**
         * 把jfreechart生成的图片转化为base64字符串
         * @param type 判断是否统计图类型  (折线图,柱状图,饼图)
         * @param series 柱状(折线)图数据
         * @param categories 类别
         * @param data 饼图数据
         * @param tile 图表标题
         * @param categoryAxisLabel 柱状(折线)图底边信息
         * @param valueAxisLabel    柱状(折线)图左侧边信息
         * @return 返回base64图片编码
         */
        public static String getImageStr(String type, Vector<Serie> series, String[] categories, Object[] data, String tile, String categoryAxisLabel, String valueAxisLabel) throws IOException {
            JFreeChart jfreechart = null;
            if("折线图".equals(type)){
                jfreechart = createChart(series,categories,tile,categoryAxisLabel,valueAxisLabel);
            }
            if("柱状图".equals(type)){
                jfreechart = createBarChart(series,categories,tile,categoryAxisLabel,valueAxisLabel);
            }
            if("饼图".equals(type)){
                jfreechart =createPieChart(data,categories,tile);
            }
            BASE64Encoder BASE64 = new BASE64Encoder();
            ByteArrayOutputStream bas = new ByteArrayOutputStream();
            try {
                assert jfreechart != null;
                ChartUtilities.writeChartAsJPEG(bas, 1.0f, jfreechart, 400, 300, null);
                bas.flush();
                bas.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            byte[] byteArray = bas.toByteArray();
            try {
                InputStream is = new ByteArrayInputStream(byteArray);
                byteArray = new byte[is.available()];
                is.read(byteArray);
                is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return BASE64.encode(byteArray);
        }
    
    
    
        /**
         * jfreechart生成图片并存放在指定位置
         * @param type 判断是否统计图类型  (折线图,柱状图,饼图)
         * @param series 柱状(折线)图数据
         * @param categories 类别
         * @param data 饼图数据
         * @param tile 图表标题
         * @param categoryAxisLabel 柱状(折线)图底边信息
         * @param valueAxisLabel    柱状(折线)图左侧边信息
         */
        public static void createPng(String type, Vector<Serie> series, String[] categories, Object[] data, String tile, String categoryAxisLabel, String valueAxisLabel) {
            JFreeChart jfreechart = null;
            if("折线图".equals(type)){
                jfreechart = createChart(series,categories,tile,categoryAxisLabel,valueAxisLabel);
            }
            if("柱状图".equals(type)){
                jfreechart = createBarChart(series,categories,tile,categoryAxisLabel,valueAxisLabel);
            }
            if("饼图".equals(type)){
                jfreechart =createPieChart(data,categories,tile);
            }
            OutputStream os;
            String imgURl=CHART_IMG_FILE + (new Date()).getTime()+".png";
            try {
                os = new FileOutputStream(imgURl);
                assert jfreechart != null;
                ChartUtilities.writeChartAsPNG(os, jfreechart, 800, 400);
                os.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        /**
         * 折线图
         */
        private static JFreeChart createChart(Vector<Serie> series, String[] categories,String tile,String categoryAxisLabel,String valueAxisLabel) {
            CategoryDataset dataset = JfreeChartStyle.createDefaultCategoryDataset(series,categories);
            //标题,x轴,y轴,数据集,图标方向,是否显示图例,是否生成工具,是否生成url
            JFreeChart line = ChartFactory.createLineChart("折线图", "时间", "销售额(百万)", dataset, PlotOrientation.VERTICAL, true,
                    true, false);
            line.setBackgroundPaint(new Color(255, 255, 255));
            //设置标题文字
            line.getTitle().setFont(new Font("黑体", Font.BOLD, 18));
            //设置底部图例字体
            line.getLegend().setItemFont(new Font("黑体", Font.BOLD, 12));
            CategoryPlot plot = line.getCategoryPlot();
            JfreeChartStyle.setLineRender(plot,true);
            JfreeChartStyle.setChartTheme();
            JfreeChartStyle.setAntiAlias(line);
            JfreeChartStyle.setLegendEmptyBorder(line);
            return line;
        }
    
    
        /**
         * 柱状图生成
         * @return 返回图表
         */
        private static JFreeChart createBarChart(Vector<Serie> series, String[] categories,String tile,String categoryAxisLabel,String valueAxisLabel){
            CategoryDataset dataset = JfreeChartStyle.createDefaultCategoryDataset(series,categories);
            //标题,x轴,y轴,数据集,图标方向,是否显示图例,是否生成工具,是否生成url
            JFreeChart barChart = ChartFactory.createBarChart(tile, categoryAxisLabel, valueAxisLabel, dataset, PlotOrientation.VERTICAL, true, true, false);
            barChart.setBackgroundPaint(new Color(255, 255, 255));
            //设置标题文字
            barChart.getTitle().setFont(new Font("黑体", Font.BOLD, 18));
            //设置底部图例字体
            barChart.getLegend().setItemFont(new Font("黑体", Font.BOLD, 12));
            CategoryPlot plot = barChart.getCategoryPlot();
            JfreeChartStyle.setBarRenderer(plot,true);
            JfreeChartStyle.setChartTheme();
            JfreeChartStyle.setAntiAlias(barChart);
            JfreeChartStyle.setLegendEmptyBorder(barChart);
            return barChart;
        }
    
        /**
         * 饼图
         */
        private static JFreeChart createPieChart(Object[] objects, String[] categories,String title){
            DefaultPieDataset dataset = JfreeChartStyle.createDefaultPieDataset(categories,objects);
            JFreeChart jFreeChart=ChartFactory.createPieChart(title, dataset,true, true,Locale.SIMPLIFIED_CHINESE);
            jFreeChart.setBackgroundPaint(new Color(255, 255, 255));
            //设置标题文字
            jFreeChart.getTitle().setFont(new Font("黑体", Font.BOLD, 18));
            //设置底部图例字体
            jFreeChart.getLegend().setItemFont(new Font("黑体", Font.BOLD, 12));
            JfreeChartStyle.setPieRender(jFreeChart.getPlot());
            return jFreeChart;
        }
    }
    

    数据实体类

    package com.qxl.wordexport.entity;
    import java.io.Serializable;
    import java.util.Vector;
    
    /**
     * 系列:名字和数据集合 构成一条曲线</br> 可以将serie看作一根线或者一根柱子:
     *
     * <p>
     * 参照JS图表来描述数据:</br> series: [{ name: 'Tokyo', data: [7.0, 6.9, 9.5, 14.5]
     * },</br> { name: 'New York', data: [-0.2, 0.8, 5.7, 11.3} ]</br>
     * </p>
     *
     */
    
    public class Serie implements Serializable {
        private static final long serialVersionUID = 1L;
        private String name;// 名字
        private Vector<Object> data;// 数据值
    
        public Serie() {
    
        }
    
        /**
         *
         * @param name
         *            名称(线条名称)
         * @param data
         *            数据(线条上的所有数据值)
         */
        public Serie(String name, Vector<Object> data) {
    
            this.name = name;
            this.data = data;
        }
    
        /**
         *
         * @param name
         *            名称(线条名称)
         * @param array
         *            数据(线条上的所有数据值)
         */
        public Serie(String name, Object[] array) {
            this.name = name;
            if (array != null) {
                data = new Vector<Object>(array.length);
                for (int i = 0; i < array.length; i++) {
                    data.add(array[i]);
                }
            }
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public Vector<Object> getData() {
            return data;
        }
    
        public void setData(Vector<Object> data) {
            this.data = data;
        }
    
    }
    

    下面是我的测试方法:

        @Test
        public void test() throws IOException {
            Vector<Serie> list=new Vector<Serie>();
            //数据1
            Serie serie=new Serie();
            Vector<Object> vector=new Vector<>();
            serie.setName("苹果");
            vector.add("2");
            vector.add("8");
            vector.add("4");
            vector.add("6");
            vector.add("8");
            serie.setData(vector);
            list.add(serie);
            //数据2
            Serie serie1=new Serie();
            Vector<Object> vector1=new Vector<>();
            serie1.setName("香蕉");
            vector1.add("5");
            vector1.add("7");
            vector1.add("4");
            vector1.add("9");
            vector1.add("3");
            serie1.setData(vector1);
            list.add(serie1);
            //数据3
            Serie serie2=new Serie();
            Vector<Object> vector2=new Vector<>();
            serie2.setName("西瓜");
            vector2.add("1");
            vector2.add("3");
            vector2.add("9");
            vector2.add("8.5");
            vector2.add("7");
            serie2.setData(vector2);
            list.add(serie2);
            //类别
            String[] categories={"一月份","二月份","三月份","四月份","五月份"};
            //饼图数据
            Object[] objects={"10","20","50","10","20"};
            //生成本地图片
            JfreeChartEntity.createPng("柱状图", list, categories, null,"这是个柱状图","这是底边类别","这是侧边信息");
            JfreeChartEntity.createPng("折线图", list, categories, null,"这是个折线图","这是底边类别","这是侧边信息");
            JfreeChartEntity.createPng("饼图", null, categories, objects,"这是个饼图","这是底边类别","这是侧边信息");
            //生成base64编码
            String imgInfo=JfreeChartEntity.getImageStr("柱状图",list,categories,null,"这是个柱状图","这是底边类别","这是侧边信息");
            String imgInfo1=JfreeChartEntity.getImageStr("折线图",list,categories,null,"这是个折线图","这是底边类别","这是侧边信息");
            String imgInfo2=JfreeChartEntity.getImageStr("饼图", null, categories, objects,"这是个饼图","这是底边类别","这是侧边信息");
            System.out.println(imgInfo);
            System.out.println("===============================================");
            System.out.println(imgInfo1);
            System.out.println("===============================================");
            System.out.println(imgInfo2);
        }

    功能完成,只需要嵌入实际业务中即可

    • 总结

    这个功能难度不高,大多是因为自己粗心造成,但是功能圆满完成还是挺开心的,同时也给自己敲响了警钟,在不清楚实际开发和使用环境之前,不要贸然下手去做,不然会浪费大量的时间成本,不过我也学到了这么多前端的图表插件,也算是很好的收获了

     

    这是本人的第一篇博客,如有错误请及时帮我纠正,欢迎一起交流技术,QQ群:826953936,QQ3293403426,微信QXL777Flower

    展开全文
  • EEP JQuery如何实现统计图表 讯光科技 前言 在ERP项目开发过程中,统计图表(chart)普遍应用于各种统计和报表中,其形象直观,内容清晰。EEP的JQuery网站项目使用了Easyui 插件并且进行了包装,但是easyui并没有...

     

    EEP JQuery如何实现统计图表

    讯光科技

    前言

    在ERP项目开发过程中,统计图表(chart)普遍应用于各种统计和报表中,其形象直观,内容清晰。EEP的JQuery网站项目使用了Easyui 插件并且进行了包装,但是easyui并没有提供图表相关的组件和实现方法。为了实现图表功能,需要使用另一些第三方JQuery图表插件来实现图表的功能。本文使用基于jQuery的开源javascript绘图库插件Flot,并结合EEP的N-Tier架构来实现简单的柱状图(barchart)和饼状图(piechart)设计。

     


    准备工作

    数据源:使用SQL Server 范例数据库Northwind 的Orders表与Order Details表。

       

     

    EEP2012:使用EEP2012的JQWebClient网站。

    Flot插件下载:http://code.google.com/p/flot/ 并且将需要使用的JS檔加入到EEP的JQWebClient网站中。
     

    Bar chart实例

    (1)   实现功能:统计1997年订单的每月销售额, 并以Barchart做比较。

    (2)   数据库语句:
    select month(orders.OrderDate) as Month,sum(Orders.TotalAmout) as TotalAmount from orders where year(orders.OrderDate)=1997 group by month(orders.OrderDate)

    (3)   建立Server端:使用SSingle模版加入一个Server端命名为SBarChart,然后将以上数据库语句复制到Master(infocommand组件)的CommandText属性上,build这个Server端工程。然后在EEPNetServer的Package Manager上加入build好的SBarChart.dll。

     

    (4)   建立Client端:在JQWebClient网站下建立一个ChartExample文件夹存放我们范例的网页,在这个文件夹下加入一个空白网页BarChart.aspx。然后加入EEP使用的js,以及Flot使用的js的参考。

     

    <!-- infolight and easyui js -->

        <link href="../js/themes/default/easyui.css" rel="stylesheet" />

        <link href="../js/themes/icon.css" rel="stylesheet" />

        <script src="../js/jquery-1.8.0.min.js"></script>

        <script src="../js/jquery.easyui.min.js"></script>

        <script src="../js/jquery.json.js"></script>

        <script src="../js/jquery.infolight.js"></script>

        <script type="text/javascript" src="../js/datagrid-detailview.js"></script> 

        <!-- flot js -->

        <!--[if lte IE 8]><script language="javascript" type="text/javascript" src="../flot-master/excanvas.min.js"></script><![endif]-->

          <script language="javascript" type="text/javascript" src="../flot-master/jquery.flot.js"></script>

          <script language="javascript" type="text/javascript" src="../flot-master/jquery.flot.categories.js"></script>

        <script language="javascript" type="text/javascript" src="../flot-master/jquery.flot.pie.js"></script>

     

    (5)   加入一个div用作图表的显示区域,加入id等属性,以及EEP使用的参数选项infolight-options

     <div id="chartid" style="width:auto;height:500px"     infolight-options="remoteName:'SBarChart.Master',tableName:'Master',xField:'Month',yField:'TotalAmount'">

         </div>

     

    (6)   加入绘制图表的JS代码。

    <script type="text/javascript">

              $(document).ready(function () {

                  var data = [];

                  var target = $('#chartid');

                  //获取参数

                  var remoteName = getInfolightOption(target).remoteName; //Server端remote

                  var tableName = getInfolightOption(target).tableName; //Server端table

                  var xField = getInfolightOption(target).xField; //X轴字段

                  var yField = getInfolightOption(target).yField; //Y轴字段

                  var url = getRemoteUrl(remoteName, tableName, false); //呼叫Server取得数据的url

                  var queryWord = new Object(); //查询条件

                  $.ajax({

                      type: "POST",

                      url: url,

                      data: "queryWord=" + $.toJSONString(queryWord),

                      cache: false,

                      async: false,

                      success: function (returndate) {

                          if (returndate != null) {

                              var rows = $.parseJSON(returndate)//将回传的字符串转换成json

                              for (var i = 0; i < rows.length; i++) {

                                  data[i] = [rows[i][xField], rows[i][yField]]; //给data数组赋值

                              }

                          }

                      },

                      error: function () {

                          alert('error');

                      }

                  });

                  $.plot(target, [data], {//将显示的数据内容给予显示的div

                      series: {

                          bars: {

                              show: true,

                              barWidth: 0.8,

                              align: "center"

                          }

                      },

                      xaxis: {

                          mode: "categories",

                          tickLength: 0

                      }

                  });

              })

          </script>

     

    (7)   在EEPManager中将这个页面挂在Menu上并且设定权限,然后通过VS开启Logon.aspx登陆浏览这个页面。

     

     

     

    Pie chart实例


    (1)   实现功能:根据不同产品代号,计算单一产品的订单总额,取产品代号1-10做成饼状图。

    (2)   数据库语句:
    select [Order Details].ProductID,sum([Order Details].UnitPrice*[Order Details].Quantity) as Amout from [Order Details] group by [Order Details].ProductID

    (3)   建立Server端:使用SSingle模版加入一个Server端命名为SPieChart,然后将以上数据库语句复制到Master(infocommand组件)的CommandText属性上,build这个Server端工程。然后在EEPNetServer的Package Manager上加入build好的SPieChart.dll。(如同SBarChart.dll的操作方式)

    (4)   建立Client端:在JQWebClient网站下的文件夹ChartExample存放我们范例的网页,在这个文件夹下加入一个空白网页PieChart.aspx。然后加入EEP使用的js,以及Flot使用的js引用。(EEP的js同BarChart.aspx的范例)

     

      <script language="javascript" type="text/javascript" src="../flot-master/jquery.flot.js"></script>

      <script language="javascript" type="text/javascript" src="../flot-master/jquery.flot.categories.js"></script>

        <script language="javascript" type="text/javascript" src="../flot-master/jquery.flot.pie.js"></script>

     

    (5)   加入一个div用作图表的显示区域,加入id等属性,以及EEP使用的参数选项infolight-options:

     <div id="chartid" style="width:auto;height:500px"     infolight-options="remoteName:'SPieChart.Master',tableName:'Master',labelField:'ProductID',valueField:'Amout'"></div>

    (6)   加入绘制图表的JS代码: 

    <script type="text/javascript">

    function labelFormatter(label, series) {

       return "<div style='font-size:8pt; text-align:center; padding:2px; color:white;'>ProcuctID: "

                 + label + "<br/> TotalAmout: " + series.data[0][1] + "</div>";

       }

        $(document).ready(function () {

            var data = [];

            var target = $('#chartid');

            //获取参数

            var remoteName = getInfolightOption(target).remoteName; //Server端remote

            var tableName = getInfolightOption(target).tableName; //Server端table

            var labelField = getInfolightOption(target).labelField; //显示的label字段

            var valueField = getInfolightOption(target).valueField; //值的字段

            var url = getRemoteUrl(remoteName, tableName, false); //呼叫Server取得数据的url

            var queryWord = new Object();

            queryWord.whereString = "ProductID >=1 and ProductID <10"; // 查询条件

            

            $.ajax({

                type: "POST",

                url: url,

                data: "queryWord=" + $.toJSONString(queryWord),

                cache: false,

                async: false,

                success: function (returndata) {

                    if (returndata != null) {

                        var rows = $.parseJSON(returndata)

                        for (var i = 0; i < rows.length; i++) {

                            data[i] = {

                                label: rows[i][labelField],

                                data: rows[i][valueField]

                            }

                        }

                    }

                },

                error: function () {

                    alert('error');

                }

            });

            //flot自身方法

            $.plot(target, data, {//将显示的数据内容给予显示的div

                series: {

                    pie: {

                        show: true,

                        radius: 1,

                        label: {

                            show: true,

                            radius: 1,

                            formatter: labelFormatter,

                            background: {

                                opacity: 0.8

                            }

                        }

                    }

                },

                legend: {

                    show: false

                }

            });

         })

      </script>

     

    在EEPManager中将这个页面挂在Menu上并且设定权限,然后通过VS开启Logon.aspx登陆浏览这个页面。

     

    结语

    以上是EEP结合Flot插件绘制柱状图和饼状图的简易范例,在设计项目的过程中我们可能不是如此简单的单一幅图,也可能并不是使用flot插件,但是方法是通用的。以此范例抛砖引玉,可以看出此类控件的3个重点,第一加入需要使用到的js引用;第二,设定先是图表的div,注意infolight-option里设定显示统计图的数据源以及图表上的所要显示的字段;第三,通过js程序读取div上设定的数据源以及显示字段(读取后转成JSON格式),并将其内容显示在div上。由此可见,利用EEP的N-Tier架构从Server端获取到数据之后,前端只要将数据转换成需要的数据形式(如JSON)交给绘图外挂组件,就能轻松完成统计图表了。

     

    转载于:https://www.cnblogs.com/yanjie-java/p/7873271.html

    展开全文
  • .net 统计图表总结

    千次阅读 2012-08-27 17:09:16
    最基本的,就是直接使用DataGrid组件和GDI+绘图直接画统计图表和报表。而使用水晶报表和activeReport等组件,其功能虽强,却需要一段时间的熟悉。水晶报表虽然名气大,vs2005自带,却并非免费,有licens

    在编写web程序时,有时需要出报表和图表,如饼状图,柱状图,折线图,曲线图等。最著名的是水晶报表,activereport,还有用友华表cell,还有其他中国人的一些报表系统。最基本的,就是直接使用DataGrid组件和GDI+绘图直接画统计图表和报表。而使用水晶报表和activeReport等组件,其功能虽强,却需要一段时间的熟悉。水晶报表虽然名气大,vs2005自带,却并非免费,有license限制。因此,对版权敏感的企业若要使用,是需要付费的,否则会承担法律后果。下面总结一些报表和统计图表资源。

    1.使用.net 2.0自带的OWC组件。

    该组件画的图比较正统,但功能都具备。可以画条形,柱形,折线,饼图等。

    示例参看青青月儿的《ASP .net 2.0 轻松搞定图表》:http://blog.csdn.net/21aspnet/archive/2007/03/27/1543320.aspx

    傅胜写的《在ASP.net中使用OWC绘制统计图表》

    http://developer.ccidnet.com/art/340/20030521/46869_1.html

    2. 使用Excel组件绘图

    Excel的统计图表是很多公司所接受和必须的。虽然它的图表不太漂亮,但功能强大,很实用。

    示例:cure的《使用C#和Excel进行报表开发 》系列http://www.cnblogs.com/dahuzizyd/archive/2006/12/20/excel_chart_3.html

    3.开源的webchart

    该webchart所绘的图形相当漂亮,支持渐变颜色,地址如下:

    http://www.codeproject.com/aspnet/WebChart.asp

     4.开源的zedgraph

    其图形也相当漂亮,支持渐变颜色。

    下载地址:http://sourceforge.net/project/showfiles.php?group_id=114675

    示例:http://zedgraph.org/wiki/index.php?title=Sample_Graphs

     5.js统计图(js chart)和jQuery插件

    Line charts、Bir charts、Pie charts

    演示地址:http://www.jscharts.com/examples
    jQuery插件地址:http://www.filamentgroup.com/lab/creating_accessible_charts_using_canvas_and_jquery/

    6.10个免费的Flash图标统计插件

    图表统计相对于文本统计更有利于给用户直观的数据显示。他们都有着广泛的应用,比如在报表应用,展示盈利,网站流量等。下面,Oli为我们收集了10个免费的在线统计图表工具的脚本或框架(Free Chart and Graph Solutions),提供给网页设计师或W eb应用开发人员。

    Open Flash Chart – Open Flash Chart是一个免费强大并且开放源代码的统计图表工具

    http://teethgrinder.co.uk/open-flash-chart/


    amCharts -amCharts提供多种样式的免费统计图表,包括饼形图表、甜甜圈样式的图表,曲线图表,分割面积图表,气泡图表和交互式地图图表等,这些图表均是免费下载

    http://www.amcharts.com/


    Php / Swf Charts – PHP/SWF Charts是一种简单但强大的PHP工具,用来从动态数据中创造有吸引力的Web统计图表。使用PHP脚本来产生或搜集来自数据库的相关数据,然后通过PHP/SWF Charts生成的 Flash统计图表。它支持任何其他脚本语言( ASP, cfml , Perl,等等来生成与XML 或SWF格式的统计图表。

    http://www.maani.us/charts/index.php


    Fusion Charts Free – Fusioncharts是一个免费的Flash图表组件,可以用来为您的Web应用程序和演示提供数据驱动和动画图表

    http://www.fusioncharts.com/goodies/fusioncharts-free/


    Yahoo! UI Library: Charts – 基于Yahoo!UI库的可视化图表,所有数据都放在一个网页上,包括的格式有:垂直柱状统计图表,横向线形图表,曲线统计图表,饼形统计图片等。

    http://developer.yahoo.com/yui/charts/


    Flot – Float是一个纯粹的基于jquery库的javascript应用 。它可以把任何数据图形化,生成一个统计图表在客户端。其外观计计非常漂亮,并且互动功能的应用比较良好,比如缩放。

    http://code.google.com/p/flot/


    SAC – 简单的查阅图表,提供一种方便、快捷的方法,以显示简单的数据和美化他们的CSS 。兼容FF ,IE6/IE7和Opera。


    Similie – Timeplot是基于Dhtmlajaxy效果演示图生,可以进行绘制时间序列和叠加基于时间的事件,支持时间线。

    http://www.simile-widgets.org/timeplot/


    PlotKit – Plotkit一个图表和图形绘制的Javascript。它支持HTML标准和SVG,也透过Adobe公司SVG的浏览器和本土浏览器支持。


    Libchart -libchart是一个免费的Flash统计图表创建,易于使用。


     XML/SWF Charts (3D)http://www.maani.us/xml_charts/index.php

    下面是一些报表和图表网上资源:

    2002年的《ASP.NET 報表建置入門套件:設計與實作》http://www.microsoft.com/taiwan/vstudio/starterkit/Reports.htm

    《报表制作利器—Reporting Services》 http://dev.21tx.com/2005/01/21/11075.html

    ActiveReports .NET    》介绍,http://www.viewslip.net/cn/tools_view_0642.html

    [C#]VC# .Net中使用Crystal Report (2004年02月07日)

    [C#]在C#中利用Excel做高级报表 (2003年06月23日)

    ASP.NET]在.NET环境下将报表导出Excel和Word (2003年06月12日)

    [ASP.NET]Asp.Net中使用水晶报表(下) (2002年06月30日)

    使用ActiveReports for .net 进行报表开发


    原文地址:http://blog.csdn.net/zhenyuanjie/article/details/7042894


    展开全文
  • .net 统计图表和报表资源总结

    千次阅读 2011-12-05 16:40:38
    最基本的,就是直接使用DataGrid组件和GDI+绘图直接画统计图表和报表。而使用水晶报表和activeReport等组件,其功能虽强,却需要一段时间的熟悉。水晶报表虽然名气大,vs2005自带,却并非免费,有licens
    
    

    在编写web程序时,有时需要出报表和图表,如饼状图,柱状图,折线图,曲线图等。最著名的是水晶报表,activereport,还有用友华表cell,还有其他中国人的一些报表系统。最基本的,就是直接使用DataGrid组件和GDI+绘图直接画统计图表和报表。而使用水晶报表和activeReport等组件,其功能虽强,却需要一段时间的熟悉。水晶报表虽然名气大,vs2005自带,却并非免费,有license限制。因此,对版权敏感的企业若要使用,是需要付费的,否则会承担法律后果。下面总结一些报表和统计图表资源。

     1.使用.net 2.0自带的OWC组件。

    该组件画的图比较正统,但功能都具备。可以画条形,柱形,折线,饼图等。

    示例参看青青月儿的《ASP .net 2.0 轻松搞定图表》:http://blog.csdn.net/21aspnet/archive/2007/03/27/1543320.aspx

    傅胜写的《在ASP.net中使用OWC绘制统计图表》

    http://developer.ccidnet.com/art/340/20030521/46869_1.html

    2. 使用Excel组件绘图

    Excel的统计图表是很多公司所接受和必须的。虽然它的图表不太漂亮,但功能强大,很实用。

    示例:cure的《使用C#和Excel进行报表开发 》系列http://www.cnblogs.com/dahuzizyd/archive/2006/12/20/excel_chart_3.html

    3.开源的webchart

    该webchart所绘的图形相当漂亮,支持渐变颜色,地址如下:

    http://www.codeproject.com/aspnet/WebChart.asp

     4.开源的zedgraph

    其图形也相当漂亮,支持渐变颜色。

    下载地址:http://sourceforge.net/project/showfiles.php?group_id=114675

    示例:http://zedgraph.org/wiki/index.php?title=Sample_Graphs

     5.js统计图(js chart)和jQuery插件

    Line charts

    Close window

    GDP 7.80
    GDP 4.80
    GDP 6.50
    GDP 6.10
    GDP 4.40
    GDP 5.80
    GDP 4.00
    GDP 8.50
    GDP 8.90
    GDP 9.20
    Close window
    Close window

    Bar charts

    U.S.A and Canada
    Close window
    Close window

    Pie charts

    Close window
    Close window
    Close window
    Close window


    演示地址:http://www.jscharts.com/examples
    jQuery插件地址:http://www.filamentgroup.com/lab/creating_accessible_charts_using_canvas_and_jquery/ 
     
     
    6.10个免费的Flash图标统计插件

    图表统计相对于文本统计更有利于给用户直观的数据显示。他们都有着广泛的应用,比如在报表应用,展示盈利,网站流量等。下面,Oli为我们收集了10个免费的在线统计图表工具的脚本或框架(Free Chart and Graph Solutions),提供给网页设计师或W eb应用开发人员。

    Open Flash Chart – Open Flash Chart是一个免费强大并且开放源代码的统计图表工具。之前有做过详细介绍,可以点击这里查看。

    114 10个免费的在线统计图表工具

    amCharts -amCharts提供多种样式的免费统计图表,包括饼形图表、甜甜圈样式的图表,曲线图表,分割面积图表,气泡图表和交互式地图图表等,这些图表均是免费下载。

    29 10个免费的在线统计图表工具

    Php / Swf Charts – PHP/SWF Charts是一种简单但强大的PHP工具,用来从动态数据中创造有吸引力的Web统计图表。使用PHP脚本来产生或搜集来自数据库的相关数据,然后通过PHP/SWF Charts生成的 Flash统计图表。它支持任何其他脚本语言( ASP, cfml , Perl,等等来生成与XML 或SWF格式的统计图表。

    33 10个免费的在线统计图表工具

    Fusion Charts Free – Fusioncharts是一个免费的Flash图表组件,可以用来为您的Web应用程序和演示提供数据驱动和动画图表。

    43 10个免费的在线统计图表工具

    Yahoo! UI Library: Charts – 基于Yahoo!UI库的可视化图表,所有数据都放在一个网页上,包括的格式有:垂直柱状统计图表,横向线形图表,曲线统计图表,饼形统计图片等。

    53 10个免费的在线统计图表工具

    Flot – Float是一个纯粹的基于jquery库的javascript应用 。它可以把任何数据图形化,生成一个统计图表在客户端。其外观计计非常漂亮,并且互动功能的应用比较良好,比如缩放。

    63 10个免费的在线统计图表工具

    SAC – 简单的查阅图表,提供一种方便、快捷的方法,以显示简单的数据和美化他们的CSS 。兼容FF ,IE6/IE7和Opera。

    73 10个免费的在线统计图表工具

    Similie – Timeplot是基于Dhtmlajaxy效果演示图生,可以进行绘制时间序列和叠加基于时间的事件,支持时间线。

    82 10个免费的在线统计图表工具

    PlotKit – Plotkit一个图表和图形绘制的Javascript。它支持HTML标准和SVG,也透过Adobe公司SVG的浏览器和本土浏览器支持。

    92 10个免费的在线统计图表工具

    Libchart -libchart是一个免费的Flash统计图表创建,易于使用。

    102 10个免费的在线统计图表工具

     XML/SWF Charts (3D)http://www.maani.us/xml_charts/index.php 

     图片

     
     

    下面是一些报表和图表网上资源:

    2002年的《ASP.NET 報表建置入門套件:設計與實作》http://www.microsoft.com/taiwan/vstudio/starterkit/Reports.htm

    《报表制作利器—Reporting Services》 http://dev.21tx.com/2005/01/21/11075.html

    ActiveReports .NET    》介绍,http://www.viewslip.net/cn/tools_view_0642.html

    [C#] VC# .Net中使用Crystal Report (2004年02月07日)

    [C#] 在C#中利用Excel做高级报表 (2003年06月23日)

    ASP.NET] 在.NET环境下将报表导出Excel和Word (2003年06月12日)

    [ASP.NET] Asp.Net中使用水晶报表(下) (2002年06月30日)

    使用ActiveReports for .net 进行报表开发 

    展开全文
  • MFC/VC++调用word进行报表制作

    千次阅读 2007-12-06 15:49:00
    MFC/VC++调用word进行报表制作 使用word进行数据报告的制作可谓非常方便,word具有非常强大的编辑、排版功能。使用word能够制作出内容丰富、样式精美的报告。我们在工作中当然会有报表报告的需求,如果能够在MFC/...
  • [转].net 统计图表和报表资源总结 .NET 2009-05-23 15:05:06 阅读33 评论0 字号:大中小订阅 转自:http://blog.csdn.net/ablo_zhou msn:ablo_zhou@hotmail.com 在编写web程序时,有时需要出报表和图表,如...
  • author:周海汉blog:http://blog.csdn.net/ablo_zhoumsn:ablo_zhou@hotmail.com在编写web程序时,有时需要出报表和图表,如饼状图,柱状图,...最基本的,就是直接使用DataGrid组件和GDI+绘图直接画统计图表和报表。而
  • MFC/VC++调用word进行报表制作

    千次阅读 2008-03-11 16:12:00
    使用word进行数据报告的制作可谓非常方便,word具有非常强大的编辑、排版功能。使用word能够制作出内容丰富、样式精美的报告。我们在工作中当然会有报表报告的需求,如果能够在MFC/VC++里面能够调用word进行word格式...
  • 先上几张图,感受下,什么叫信息图表,什么叫信息可视化。如果你在某个稍具规模的公司混,或者,你需要在某个特定场合展示你的数据。这种图就能大大的派上用场。它的好处显而易见:可以装逼很清晰的展示数据,化平庸...
  • emw.createWord(map, "统计表.ftl", fileName); try { response.setContentType("application/octet-stream;charset=utf-8"); response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder....
  • 如何修缮图像瑕疵、污点 如何运用抠图技术以满足论文及幻灯片需求 照片、条带、图表的的排版 电泳条带胖瘦不一或者歪斜图片该如何处理 条带的灰度分析和测量IOD值 多图像的排版 图表制作中存在的问题 图表的修改和...
  • .net生成word报表

    2016-08-08 14:00:33
    在系统里,直接引用该文件,可以进行word报表的制作,往里面添加 文字、统计图表等。这条、引用的COM组件版本 C:\Windows\assembly\GAC_MSIL\Microsoft.Office.Interop.Excel\14.0.0.0__71e9bce111e9429c\Microsoft....
  • 科研论文插图/数据处理和图表制作学习会2019年12月27-29日上海,26号报到,现场赠送8gU盘和高清视频供课后复习使用主讲老师金老师来自中科院系统。在医学生物科研一线岗位10余年...
  • 1、安装库: pip install pyecharts 2、词云: shape参数用来调整词云形状, word_size_ragne限定字体大小范围,更多参数请参考API ...3、统计图表(饼状图,条形图,折线图): shape参数用来调整...
  • 原贴:http://www.itwen.com/03office/01word/word20060413/43117.html 编排目录去掉页脚的关键是把文档分成几块几块的,然后单独来处理!插入分隔符!点击下一页,每次的分隔符都是首页设计的不一样;且要自动生成...
  • A、选定整表 B、选定若干行 C、选定若干列 D、不选定2、用Word2000的表格可以进行操作是( A B D )A、表格数据的统计计算B、表格数据的排序C、表格转换为文本框D、用表格数据制作统计图表。3、在编辑状态,被编辑文档...
  • word技巧

    千次阅读 2018-03-01 21:40:22
    word 高效经典教程(整理版)目录一分钟驾驭word 高效经典教程(整理版)... 6A、基础知识... 61、度量单位... 62、WORD中文字字号与磅的对应关系... 63、字体文件格式... 7B、文本编辑... 71、快速移动文档... 72、...
  • (全文共计1485字,预计阅读时间为4分钟)导读:经典回顾:【强烈推荐】2天让你学会撰写影像组学SCI论文#内含福利#科研论文插图/数据处理和图表制作学习会2019年12月27-29日上海26号报到现场赠送8G优盘和高清视频...
  • echarts 生成统计图时,自动保存图片到服务器,并使用freemarker生成word。 1.项目工程截图如下: 需要echarts包和生成word的freemarker-2.3.8.jar包 2.index.jsp页面中的代码: String path = ...
  • word精彩实例互动教程》...1、Word互动教程是一款简单、有趣、互动式的学习Office Word 2019的新工具。此应用将向您展示Word 2019的绝大部分功能点。 2、应用包含大量操作提示,指导您一步一步地实现Office Wo...
  • counts[rword] = counts.get(rword,0) + 1 #字典的运用,统计词频P167 for word in excludes: #删除之前所规定的词语 del (counts[word]) items = list(counts.items()) #返回所有键值对P168 items.sort(key=...
  • 好文网为大家准备了关于PHP生成WORD表格的文章,好文网里面收集了五十多篇关于好PHP生成WORD表格好文,希望可以帮助大家。更多关于PHP生成WORD表格内容请关注好文网。ctrl+D请收藏!篇一:PHP导出Word文档原理好文网为...
  • 线上学习班建群答疑可以回放 终生免费复听一对一个性化服务本公司还推出一对一个性化服务,主要包括1)矢量流程图绘制(流程图、机制图、封面图、论文摘要图)2)图片...统计分析)如您有此需求或其他科研个性化一对一服...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 4,399
精华内容 1,759
关键字:

word统计图表制作