C#实现数据导出任一Word图表的通用呈现方法及一些体会

这篇具有很好参考价值的文章主要介绍了C#实现数据导出任一Word图表的通用呈现方法及一些体会。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

疲惫的修改

应人才测评产品的需求,导出测评报告是其中一个重要的环节,报告的文件类型也多种多样,其中WORD输出也扮演了一个重要的角色。

实现方法比较简单,结合分析结果数据,通过WORD模板文件进行替换输出。在实现的过程中,图表的设计是必不可少的,根据初次产品的设计方案,图表采用微软Chart图表控件进行开发,采用雷达图进行呈现。使用该控件首先要引入 System.Web.DataVisualization.dll 程序集,通过定义 System.Web.UI.DataVisualization.Charting.Chart 类来实现,本来采用该开发方案的初衷是觉得都是微软的技术,图表的呈现类型也比较丰富,可在实际的开发中,情况没有想像的那么顺利,提供的技术文档非常有限,各种百度也是凤毛麟角,经过努力与探索,最终还是实现了需求。

但后来由于种种原因,图表要求采用饼状3D图进行呈现,虽然已经有了第一次的经验,但细节的变化,不得不再次进行探索和学习,可当需求再次改变的时候,我决定游说产品设计和改变设计思路。

新的思路

由于引入 Microsoft.Office.Interop.Word 程序集进行开发,因此在Word上的所有操作都能用程序去实现,其内置的图表功能也不例外,通过演练和内部讨论,图形化的呈现基本能够满足需求。

通用性

举例,我们在Word中插入一个图表并选择雷达图,如下图:

C#实现数据导出任一Word图表的通用呈现方法及一些体会,微软Office计算中心,c#,开发语言

插入后,我们看到 Word 会自动弹出一个微缩版的 Excel 应用,改变其中的项和系列值,图表就会对应的产生变化。  

我们右击雷达图,选择更改图表类型为饼图,如下图:

C#实现数据导出任一Word图表的通用呈现方法及一些体会,微软Office计算中心,c#,开发语言

可以看到饼图按照EXCEL数据中的系列1数据进行呈现,也不会因为系列2的数据存在而出现错误。由此可以分析出,控制好这个 Excel 的数据应用即可按照我们的设计实现任一图表的输出。

设计方案

(1)负责具体业务的应用程序,输出后的数据,存入一个二维字符串数组里,模拟 Excel 数据存储模式。

(2)考虑未来的扩展性,将二维数组转化为Json数据格式,并添加一个查找关键字节点,假设为“ t:chart1”。

(3)在 Word 模板设计图表,图表的标题设置为Json对应的查找关键字,即“ t:chart1”。

(4)编写数据导出EXCEL方法,传递JSON字符串参数,读取Word模板文件,遍历模板文件中的图表对象,并按查找关键字与图表的标题进行对比,匹配成功,则将JSON中数组转化为图表需要的EXCEL数组形式,到此输出完毕。

为什么用 Json 过渡

我们的云架构里设计了一个 Office 计算中心,在某些环境下,比如 Linux 中需要这种方式传递并返回值,以达到导入导出Office文件的目的。所以大家要根据实际的应用进行设计,这里仅作为参考。

关键代码实现

开发环境

操作系统:Windows Server 2019 DataCenter

开发工具:VisualStudio2019 

框架及语言:.net 4.7.1     C#

服务上需要安装 Office 2016或以上

现在开始!

在此我们以最易懂的代码形式举例,假设文件模板中的图表为条状图,关键查找字(图表标题)设为 “ t:chart1”,如下图:

C#实现数据导出任一Word图表的通用呈现方法及一些体会,微软Office计算中心,c#,开发语言

(1)创建二维数组

            //定义二维字符串数组,第一列为项目名称,第二列为值
            string[,] chart1 = new string[11, 2];
            chart1[0, 0] = "项";
            chart1[0, 1] = "值";
            chart1[1, 0] = "全局观";
            chart1[2, 0] = "影响力";
            chart1[3, 0] = "公正性";
            chart1[4, 0] = "果敢性";
            chart1[5, 0] = "执行力";
            chart1[6, 0] = "人际理解";
            chart1[7, 0] = "成就意识";
            chart1[8, 0] = "创新意识";
            chart1[9, 0] = "情绪控制";
            chart1[10, 0] = "学习发展";
            Random rnd = new Random();
            for (int si = 1; si <= 10; si++)
            {
                chart1[si, 0] = rnd.NextDouble().ToString(); //循环赋值随机浮点数
            }

(2)二维数组转Json格式

这里引入 Newtonsoft.Json.dll 程序集进行操作,代码如下:

    StringWriter sw = new StringWriter();   //using System.IO
    using (Newtonsoft.Json.JsonWriter writer = new Newtonsoft.Json.JsonTextWriter(sw))
            {
                writer.Formatting = Newtonsoft.Json.Formatting.Indented;
                writer.WriteStartObject();

                //t:chart1  转化数组chart1 为 json 对象

                writer.WritePropertyName("t:chart1");
                writer.WriteStartArray();

                writer.WriteStartObject();
                writer.WritePropertyName("col1");
                writer.WriteValue(chart1[0, 0]);
                writer.WritePropertyName("col2");
                writer.WriteValue(chart1[0, 1]);
                writer.WriteEndObject();
                for (int r = chart1.GetLength(0) - 1; r > 0; r--)
                {
                    writer.WriteStartObject();
                    //循环写入列2的具体值
                    for (int c = 0; c < 2; c++)
                    {
                        writer.WritePropertyName("col" + (c + 1).ToString());
                        writer.WriteValue(chart1[r, c]);
                    }
                    writer.WriteEndObject();
                }
                writer.WriteEndArray();
                //t:chart1

                writer.WriteEndObject();
                writer.Flush();
            }
            sw.Close();
            string jsonContent = sw.GetStringBuilder().ToString();  //得到最终json字串

转化成功的样例如下:

{
"t:chart1": [
    {
      "col1": "项",
      "col2": "值"
    },
    {
      "col1": "学习发展",
      "col2": "4.1"
    },
    {
      "col1": "情绪控制",
      "col2": "5"
    },
    {
      "col1": "创新意识",
      "col2": "5.1"
    },
    {
      "col1": "成就意识",
      "col2": "4.8"
    },
    {
      "col1": "人际理解",
      "col2": "4"
    },
    {
      "col1": "执行力",
      "col2": "5"
    },
    {
      "col1": "果敢性",
      "col2": "5.7"
    },
    {
      "col1": "公正性",
      "col2": "4.5"
    },
    {
      "col1": "影响力",
      "col2": "4.7"
    },
    {
      "col1": "全局观",
      "col2": "4.2"
    }
  ]
}

 

(3)查找图表且替换数据

本代码程序只是示例片断,非完整程序,仅供参考。

一些引用
using Word=Microsoft.Office.Interop.Word;
using Newtonsoft.Json.Linq;


转换 json 字符串为 json 对象

Newtonsoft.Json.Linq.JObject jObject = null;
            if (jsonContent != "")
            {
                try
                {
                    jObject = Newtonsoft.Json.Linq.JObject.Parse(jsonContent); //转换为json对象
                }
                catch (Exception e)
                {
                    resultReport += "create json object  fail.<br>";  //失败记入调试报告
                }
            }

初始化 Word 应用程序

			Word.Application WordApp=new Word.Application();
            
			//创建一个名为WordDoc的文档对象
			WordApp.DisplayAlerts=Word.WdAlertLevel.wdAlertsNone;  //禁止一切提示警告
            //打开 filename 的文件
			Word.Document WordDoc=WordApp.Documents.Open(ref filename,ref Nothing,ref Nothing,ref Nothing,ref Nothing,ref Nothing,ref Nothing,ref Nothing,ref Nothing,ref Nothing,ref Nothing,ref Nothing,ref Nothing,ref Nothing,ref Nothing,ref Nothing);
            //禁用拼写检查
            WordDoc.SpellingChecked = false;
            WordDoc.ShowSpellingErrors = false;



遍历word 里的 shapes

for (int i = 1; i <= WordDoc.InlineShapes.Count; i++)
{
  Word.InlineShape shape = WordDoc.InlineShapes[i];  //得到 shape对象
   //遍历 json 对象
  foreach (var item in jObject)
  {
    string tcmd = item.Key.ToString();   //取关键字
    //如果 shape 包含图表,则继续
    if (shape.HasChart == Microsoft.Office.Core.MsoTriState.msoTrue)
    {
        //如果图表未设置标题,则短路
        if (shape.Chart.HasTitle == false)
        {
            continue;
        }
        //获取图表的title
        string _name = shape.Chart.ChartTitle.Text.Trim().ToLower();
        if (_name.IndexOf(tcmd) != -1) //如果包含关键字则继续
        {
            //替换掉关键字,保留下来的是真正的标题
           shape.Chart.ChartTitle.Text = shape.Chart.ChartTitle.Text.Replace(tcmd, "");

            //这是一个玄机,否则会报错,目前我是这样的解决,A1:Z100,先赋值为空串
           shape.Chart.ChartData.Workbook.Worksheets[1].Range("A1:Z100").Value = "";
            //计算最后的单元格地址
           string lastcellAddress = "$" + ((char)(64 + jObject[tcmd][0].Count())).ToString() + "$" + jObject[tcmd].Count().ToString();
           //获得最终地址字串 
           string sourceDataAddress = "='Sheet1'!$A$1:" + lastcellAddress;

           //遍历json对象节点里的数组
           for (int i = 0; i < jObject[tcmd].Count(); i++)
           {
                List<JToken> tokens = jObject[tcmd][i].ToList();
                int k = 0;
                foreach (JToken jToken in tokens)
                {
                  //为每一个单元格赋值
                  string celladdress = ((char)(65 + k)).ToString() + (i + 1).ToString();                                shape.Chart.ChartData.Workbook.Worksheets[1].Range(celladdress).Value = jToken.ToArray()[0].ToString();
                  k++;
                }
           }
           shape.Chart.SetSourceData(sourceDataAddress);  //设置更新图表的数据源
           break;
         } // index of name
      } // has chart

   }//foreach tcmd


} //WordDoc.InlineShapes


 小结

通过这种设计可以实现任意更换图表的类型,基本无需关注图表的实现原理,而让开发人员更多的关注于业务逻辑,当然这些图表的种类受限于Word的提供能力,如果能够满足需求,不失为一种解决思路。另外,我们可以继续扩展程序的功能,实现动态的图表添加或切换能力等。

一些体会

作为一名全程管理加全栈开发的 “野战军”,更多的时候考虑的是满足需求、稳定功能和控制各种成本,而无法深入地研究各项领域。随着年龄的增长,唯一能做到的就是业务经验弥补精力和学习时间的不足,还是有几点体会与大家共勉吧:

1、后悔学生时代没有端正态度和认识到认真学习的重要性,所谓书到用时方恨少,熟练掌握修炼数据结构与算法、数学等程序员的内功至关重要。

2、语言只是一种模型和工具而已,可先从一门语言入手到实际应用,抽象的来看所有语言总体上都是大同小异,后来会觉得学习一门新语言是一件非常有趣的事。

3、时间允许的情况下还是要深入掌握一些底层的技术开发和原理,这至少是一件非常有趣的事。

4、在工作中平衡最为关键,也包括人,换位思考很重要。

5、提升设计能力、业务处理能力和总结学习方法尤为关键。

以上就是自己一些体会,时间仓促,不妥之处还请大家批评指正讨论,程序员节就要到啦,祝咱们永远保持年轻的心,健康的心态,用智慧编写美好的人生!文章来源地址https://www.toymoban.com/news/detail-713123.html

到了这里,关于C#实现数据导出任一Word图表的通用呈现方法及一些体会的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • java实现将数据导出为word功能(文字,表格,图片的循环导出)

    这里需要注意的点!!!!!!!!!!!!!!!!! easypoi的版本必须在4.3.0以上,否则在导出图片的时候,只会导出图片的内存地址,却不能显示出图片。  解释一下模板中所填充的东西: 1.像这种:用两个花括号括起来的变量名,到时候会将变量名所指代的数据填充进

    2024年02月02日
    浏览(46)
  • C#实现对Access数据库的通用操作

      ①实现创建Access数据库;   ②实现创建指定Access数据库的表;   ③实现给Access数据库的指定表【插入、查询、更新、删除、分页查询】数据;   ④实现获取Access数据库中的所有表名称及其表包含的所有列名称 该项目的完整工程下载地址如下: Access数据库操作项目的完整工程

    2024年02月08日
    浏览(58)
  • C#使用第三方库ExcelDataReader读取excel数据并呈现

    之前有使用Oledb读取Excel的代码:C#读取excel数据并呈现 使用这种方式读取存在需要安装数据库引擎的隐患(如需要自取)

    2024年02月13日
    浏览(43)
  • C#使用DateTime.Now.AddDays方法获取任一天的信息

    目录 一、使用DateTime对象的AddDays方法获取任一天信息方法 二、举例说明获取昨天的信息 三、涉及到的知识点 1. MessageBox.Show()中信息分行的办法         使用DateTime.Now属性可以得到当前的日期信息,此时调用ToString方法,并在该方法中添加指定的格式化字符串,可以按照

    2024年01月25日
    浏览(36)
  • vue2 若依项目,使用plotly.js-dist图表库,将数据图表一键导出为图片

    此代码适用的场景是一个页面有多个数据图表。 首先需要拿到你生成数据图表的数据, 然后赋值给一个数组,数组需要在data定义,还需要去重。  然后点击导出按钮的代码如下: 单个下载可以点击数据图表的照相机,可以实现单个下载。 如果数据图表做了分页和懒加载,无

    2024年02月12日
    浏览(46)
  • 使用EasyExcel实现通用导出功能

    JDK 1.8+ EasyExcel 2.2.7 此功能可以实现根据传入自定义的 导出实体类或Map 进行excel文件导出。若根据Map导出,导出列的顺序可以自定义。 话不多说,直接看代码 点击查看代码 点击查看代码 点击查看代码 点击查看代码 点击查看代码 点击查看代码 点击查看代码

    2024年02月05日
    浏览(25)
  • 数据导出excel的通用python代码

    在实际的项目开发中,一些重要数据需要保存到excel文件中,或者需要提供下载的功能,都会用到将数据导出excel的代码。 本文介绍了将数据导出excel的通用python代码,对创建excel文件、写数据等过程进行了封装,开箱即用,且可复用。 测试上述代码,生成的excel文件如下图所

    2024年02月02日
    浏览(46)
  • 使用freemarker,数据导出word并下载

    1.1 项目背景 最近在开发一个项目,需要导出一些数据,然后写入到word文档中,然后再导出到本地,这个需求是比较常见的,但是我在网上找了很多资料,都没有找到一个比较好的解决方案,所以就自己写了一个,这里分享给大家,希望能帮助到大家。 项目中使用的技术栈:

    2024年02月05日
    浏览(36)
  • Java 实现导出 Word 文档的方法详解

    前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站,这篇文章男女通用,看懂了就去分享给你的码吧。 在 Java 应用程序中,有时候我们需要将数据导出为 Word 文档,以便进行文档的编辑、打印或共享。本文将介绍如何

    2024年02月15日
    浏览(41)
  • vue若依导出word文件,简单的实现

    首先前端导包,注意exportDocx的导包位置要修改成你自己的 然后新建一个测试按钮 接下来是js文件 然后将下面这个docutil.js文件复制到项目中,我是复制在utils/docUtil中 最后新建一个word模板文件,保存的格式要是docx才行哦 例如: 只要数据是集合,就得是{#list} 开头{/list}结尾 如果还有

    2024年02月11日
    浏览(30)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包