首页 > 其他分享 >将ECharts图表插入到Word文档中

将ECharts图表插入到Word文档中

时间:2023-11-15 11:47:14浏览次数:33  
标签:Word args js 文档 new var params height ECharts

@

目录
如何通过ECharts在后台生成图片,然后插入到Word文档中?

首先要解决一个问题:总所周知,ECharts是前端的一个图表库,如何在后台调用JS代码?这里就要用到PhantomJS了。

PhantomJS是一个基于WebKit的JavaScript API,它使用QtWebKit作为核心浏览器的功能,使用WebKit编译、解释和执行JavaScript代码。任何可以在基于WebKit的浏览器上做的事情,它都能做到。它不仅是一个隐形的浏览器,提供了诸如CSS选择器、支持Web标准、DOM操作、JSON、HTML5、Canvas、SVG等功能,同时也提供了处理文件I/O的操作。

之前写过一个文档模板工具,其中可以通过占位符插入图片。

用PhantomJS生成ECharts图表的Png图片,利用文档模板工具插入图片即可实现这个需求。

下面就来看看如何实现。

在后端调用JS代码

创建一个.netstandard2.1的类库项目。为了方便调用,我们安装一个PhantomJS包装器:NReco.PhantomJS

dotnet add package NReco.PhantomJS --version 1.1.0

这只是一个包装器,因此还需要一个可执行文件,前往官网下载PhantomJS。

因为直接使用编译好的可执行文件,因此需要下载对应的平台版本,这里我下载了Windows以及Linux 64-bit版本。

将下载好的可执行文件解压放置在项目根目录下的libs目录中。

在这里插入图片描述

这样我们可以直接在.net中调用PhantomJS了。

准备ECharts库

jQuery

下载jquery-3.6.3.min.js: https://code.jquery.com/jquery-3.6.3.min.js

ECharts

下载echarts.min.js: https://github.com/apache/echarts/tree/5.4.3/dist

ECharts转换器

echarts-convert在github上有众多版本,echarts-convert的代码来源于这里:https://github.com/wadezhan/billfeller.github.io/issues/85

这里选择

(function () {
    var system = require('system');
    var fs = require('fs');
    var config = {
        // define the location of js files
        JQUERY: 'jquery-3.6.3.min.js',
        //ESL: 'esl.js',
        ECHARTS: 'echarts.min.js',
        // default container width and height
        DEFAULT_WIDTH: '1920',
        DEFAULT_HEIGHT: '800'
    }, parseParams, render, pick, usage;

    usage = function () {
        console.log("\nUsage: phantomjs echarts-convert.js -options options -outfile filename -width width -height height"
            + "OR"
            + "Usage: phantomjs echarts-convert.js -infile URL -outfile filename -width width -height height\n");
    };

    pick = function () {
        var args = arguments, i, arg, length = args.length;
        for (i = 0; i < length; i += 1) {
            arg = args[i];
            if (arg !== undefined && arg !== null && arg !== 'null' && arg != '0') {
                return arg;
            }
        }
    };

    parseParams = function () {
        var map = {}, i, key;
        console.log("--logs:\n")
        console.log(system.args)
        if (system.args.length < 2) {
            usage();
            phantom.exit();
        }
        for (i = 0; i < system.args.length; i += 1) {
            if (system.args[i].charAt(0) === '-') {
                key = system.args[i].substr(1, i.length);
                if (key === 'infile') {
                    // get string from file
                    // force translate the key from infile to options.
                    key = 'options';
                    try {
                        map[key] = fs.read(system.args[i + 1]).replace(/^\s+/, '');
                    } catch (e) {
                        console.log('Error: cannot find file, ' + system.args[i + 1]);
                        phantom.exit();
                    }
                } else {

                    map[key] = system.args[i + 1].replace(/^\s+/, '');
                }
            }
        }
        return map;
    };

    render = function (params) {
        var page = require('webpage').create(), createChart;

        var bodyMale = config.SVG_MALE;
        page.onConsoleMessage = function (msg) {
            console.log(msg);
        };

        page.onAlert = function (msg) {
            console.log(msg);
        };

        createChart = function (inputOption, width, height, config) {
            var counter = 0;
            function decrementImgCounter() {
                counter -= 1;
                if (counter < 1) {
                    console.log(messages.imagesLoaded);
                }
            }

            function loadScript(varStr, codeStr) {
                var script = $('<script>').attr('type', 'text/javascript');
                script.html('var ' + varStr + ' = ' + codeStr);
                document.getElementsByTagName("head")[0].appendChild(script[0]);
                if (window[varStr] !== undefined) {
                    console.log('Echarts.' + varStr + ' has been parsed');
                }
            }

            function loadImages() {
                var images = $('image'), i, img;
                if (./Assets/images.length > 0) {
                    counter = images.length;
                    for (i = 0; i < images.length; i += 1) {
                        img = new Image();
                        img.onload = img.onerror = decrementImgCounter;
                        img.src = images[i].getAttribute('href');
                    }
                } else {
                    console.log('The images have been loaded');
                }
            }
            // load opitons
            if (inputOption != 'undefined') {
                // parse the options
                loadScript('options', inputOption);
                // disable the animation
                options.animation = false;
            }

            // we render the image, so we need set background to white.
            $(document.body).css('backgroundColor', 'white');
            var container = $("<div>").appendTo(document.body);
            container.attr('id', 'container');
            container.css({
                width: width,
                height: height
            });
            // render the chart
            var myChart = echarts.init(container[0]);
            myChart.setOption(options);
            // load images
            loadImages();
            return myChart.getDataURL();
        };

        // parse the params
        page.open("about:blank", function (status) {
            // inject the dependency js
            page.injectJs(config.ESL);
            page.injectJs(config.JQUERY);
            page.injectJs(config.ECHARTS);


            var width = pick(params.width, config.DEFAULT_WIDTH);
            var height = pick(params.height, config.DEFAULT_HEIGHT);

            // create the chart
            var base64 = page.evaluate(createChart, params.options, width, height, config);
            //fs.write("base64.txt", base64);
            // define the clip-rectangle
            page.clipRect = {
                top: 0,
                left: 0,
                width: width,

                height: height
            };
            // render the image
            page.render(params.outfile);
            console.log('render complete:' + params.outfile);
            // exit
            phantom.exit();
        });
    };
    // get the args
    var params = parseParams();

    // validate the params
    if (params.options === undefined || params.options.length === 0) {
        console.log("ERROR: No options or infile found.");
        usage();
        phantom.exit();
    }
    // set the default out file
    if (params.outfile === undefined) {
        var tmpDir = fs.workingDirectory + '/tmp';
        // exists tmpDir and is it writable?
        if (!fs.exists(tmpDir)) {
            try {
                fs.makeDirectory(tmpDir);
            } catch (e) {
                console.log('ERROR: Cannot make tmp directory');
            }
        }
        params.outfile = tmpDir + "/" + new Date().getTime() + ".png";
    }

    // render the image
    render(params);
}());

将上述文件放在项目根目录下的js目录中。

在这里插入图片描述

我们来测试一下是否能生成一个简单的ECharts图表。

创建一个option.json

在这里插入图片描述

首先指定一个option,在官方示例 https://echarts.apache.org/examples/zh/index.html 中,随意找一个柱状图的sample,复制option对象内容到新创建的option.json文件中

{
  "tooltip": {
    "trigger": "axis",
    "axisPointer": {
      "type": "shadow"
    }
  },
  "grid": {
    "left": "3%",
    "right": "4%",
    "bottom": "3%",
    "containLabel": true
  },
  "xAxis": [
    {
      "type": "category",
      "data": [ "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun" ],
      "axisTick": {
        "alignWithLabel": true
      }
    }
  ],
  "yAxis": [
    {
      "type": "value"
    }
  ],
  "series": [
    {
      "name": "Direct",
      "type": "bar",
      "barWidth": "60%",
      "data": [ 10, 52, 200, 334, 390, 330, 220 ]
    }
  ]
}

Program.cs中调用ECharts转换器:

static void Main(string[] args)
{
    var phantomJS = new PhantomJS();

    if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
    {
        phantomJS.ToolPath = Path.Combine(basePath, "libs\\phantomjs-2.1.1-windows\\bin");

    }
    else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
    {
        phantomJS.ToolPath = Path.Combine(basePath, "libs\\phantomjs-2.1.1-linux-x86_64\\bin");

    }
    var scriptPath = Path.Combine(basePath, "js\\echarts-converts.js");

    var optionPath = Path.Combine(basePath, "js\\option.json");

    phantomJS.OutputReceived += (sender, e) =>
    {
        Console.WriteLine("PhantomJS output: {0}", e.Data);
    };
    
    phantomJS.Run(scriptPath, new string[] { "-infile", optionPath });
    phantomJS.Abort();

}

打印如下

在这里插入图片描述

打开输出路径看到生成的图片。

在这里插入图片描述

生成Word文档

为了方便集成,我加.NET中构件ECharts中可能用的全部数据结构。
这里感谢https://github.com/idoku/EChartsSDK这个项目,代码基本都是从这里拷贝过来的。

这样可以通过指定ChartOption对象,生成图片。

var option = new ChartOption()
    {
        title = new List<Title>()
        {
            new Title (){
            text=title, left="center"}
        },
        tooltip = new ToolTip(),
        legend = new Legend()
        {
            orient = OrientType.vertical,
            left = "left"
        },
        series = new object[]
        {
            new {
                name= "Access From",
                type="pie",
                data=new object[]
                    {
                        new  { value= failedCount, name="异常" },
                        new  { value= passCount, name="正常" },
                    }
            }
        }
    }

根据Document Template Tool图片占位符格式:#字段名称[宽度,高度]#,

在上一章的Sample基础上,在ReportTemplate2.docx中添加图片占位符。

在这里插入图片描述

生成后的文档如下:

在这里插入图片描述

项目地址

库封装

https://github.com/jevonsflash/EChartsGen

本文示例 EChartsGen_DocTemplateTool_Sample

https://github.com/jevonsflash/EChartsGen/tree/master/EChartsGen_DocTemplateTool_Sample

标签:Word,args,js,文档,new,var,params,height,ECharts
From: https://www.cnblogs.com/jevonsflash/p/17833456.html

相关文章

  • 软件开发项目文档系列之十六如何撰写系统运维方案
    @目录前言1硬件和软件基础设施1.1服务器和网络设备1.2软件和操作系统1.3数据库管理2监控和警报2.1系统监控2.2应用程序监控2.3日志管理3备份和恢复3.1数据备份3.2灾难恢复计划4安全性4.1安全策略4.2安全审计5团队组织和沟通5.1运维团队5.2沟通计划6结论前言项......
  • play wordle
    好像烂大街了。。。这里用的词库有\(8869\)个词。先形式化wordle游戏:给定词库\(S\),所有词的长度为\(5\),要求你猜一个词\(w\),每一轮可以输入一个词\(s\),并返回一个长为\(5\)的数列\(r\):\[r_i=\begin{cases}0,&s_i\neqw_i,\forallj,s_i\neqw_j\\1,&s_i\neqw_i......
  • JavaDoc生成文档(也就是文档注释)
    一、JavaDoc1.javadoc命令是用来生成自己API文档的2.参数信息@author作者名@version版本号@since指明需要最早使用的jdk版本@param参数名@return返回值情况@throws异常抛出情况 ......
  • java 使用documents4j将word转pdf
    documents4j简介document4j是一个用来进行文档格式转换的Java工具库,它通过借助本机中支持指定文件格式到目标文件格式转换的应用,来实现整个转换的过程。document4j实现了MicrosoftWord、Excel的适配功能,可以将docx文件转换为pdf文件,并且在这个过程中不会出现非微软文件转换出......
  • CS224n笔记:word2vec(1)
    目录离散语义(discrete):分布语义(distribute):tokens、types分布的语言模型(distributionallanguagemodel):词嵌入模型Word2VecObjectivefunc(目标函数)Lossfunc(损失函数)P(O|C)和Softmax(x)P(O|C)的概率分布将损失函数展开求梯度公式损失函数的时间复杂度ChainRule:链......
  • 智能化工业园区设计方案-(180页 WORD版)
    智慧化工园区建设致力于通过先进的信息技术和数据管理系统,实现对工业过程的监控、分析和优化,从而提升运营效率并优化资源配置。通过实时监测和分析生产数据,管理者可以更好地了解工艺流程,发现潜在问题并进行及时干预,从而降低生产成本和风险。·数字化技术在智慧化工园区建设中扮演着......
  • 秦疆的Java课程笔记:32 基础 JavaDoc生成文档
    javadoc命令是用来生成自己API文档的参数信息:@author作者名@version版本号@since指明需要最早使用的JDK版本@param参数名@return返回值情况@throws异常抛出情况比如这就是一个JDK21的Oracle官方API:点击跳转packageacolyte.operator;/***这是加在类......
  • echarts实现柱状图自动轮播/鼠标悬浮悬停
    1.dataZoom配置dataZoom:[//滑动条{xAxisIndex:0,//这里是从X轴的0刻度开始show:false,//是否显示滑动条,不影响使用type:"inside",//这个dat......
  • 微信机器人开发文档
    请求URL:http://域名地址/sendText请求方式:POST请求头Headers:Content-Type:application/jsonAuthorization:login接口返回参数:参数名必选类型说明wId是string登录实例标识wcId是string接收人微信id/群idcontent是string文本内容消息返回数据:参数名类型说明codestring1000成功,1001失败m......
  • 软件开发项目文档系列之十五如何撰写项目结项报告
    这是一个项目总结文档的说明文件,它提供了项目的概述、建设情况、技术情况、测试情况、培训情况、试运行情况、主要成效等详细信息。1项目概述项目名称:明确指定了项目的名称,这有助于确保文件的清晰性和易读性。项目相关单位:明确列出了与项目相关的合作单位,以及它们在项目中的......