C#實(shí)現(xiàn)導(dǎo)出Word圖表通用方法之散點(diǎn)圖
特殊之處
《C#實(shí)現(xiàn)數(shù)據(jù)導(dǎo)出任一Word圖表的通用呈現(xiàn)方法及一些體會(huì)》一文講解了數(shù)據(jù)導(dǎo)出生成 WORD 圖表的通用方法, 根據(jù)應(yīng)用需求,大部分的圖表(如柱形圖)如下設(shè)置:

插入后,微縮版 Excel 應(yīng)用顯示了一些通用的數(shù)據(jù)設(shè)置,類別項(xiàng)和系列項(xiàng)的數(shù)值,改變其中的項(xiàng)和系列值,圖表就會(huì)產(chǎn)生相應(yīng)的變化。
對(duì)于像單一數(shù)據(jù)來源的,如雷達(dá)圖:

可以設(shè)置必要項(xiàng),分類和系列1,而不會(huì)因?yàn)橄盗?的數(shù)據(jù)存在而出現(xiàn)錯(cuò)誤,WORD會(huì)自動(dòng)“忽略”。但最近在新需求應(yīng)用中,使用一款散點(diǎn)類型圖表時(shí)發(fā)現(xiàn)了一些問題,其EXCEL數(shù)據(jù)源如下:

與柱狀圖、餅狀圖的格式不同,散點(diǎn)圖是 X值和Y值的列名+二維數(shù)組設(shè)置。但實(shí)際的操作實(shí)現(xiàn)可能需要進(jìn)行類似如下的設(shè)置:

即模擬去掉列名,直接輸出數(shù)據(jù),可正常進(jìn)行顯示輸出 ,因此我們需要對(duì)通用方法進(jìn)行一些改造。
設(shè)計(jì)方案
仍遵循原設(shè)計(jì)方案基礎(chǔ),將業(yè)務(wù)數(shù)據(jù)存入一個(gè)二維字符串?dāng)?shù)組,并轉(zhuǎn)化為Json數(shù)據(jù)格式,并添加一個(gè)查找關(guān)鍵字節(jié)點(diǎn),假設(shè)為“ t:chart1”。在 Word 模板插入散點(diǎn)圖圖表,圖表的標(biāo)題設(shè)置為Json對(duì)應(yīng)的查找關(guān)鍵字,即“ t:chart1”。最后,讀取Word模板文件,遍歷模板文件中的圖表對(duì)象,并按查找關(guān)鍵字與圖表的標(biāo)題進(jìn)行對(duì)比,匹配成功,則將JSON中數(shù)組轉(zhuǎn)化為圖表需要的EXCEL數(shù)組形式,完成圖表繪制輸出。
經(jīng)調(diào)試,首列單元格需要設(shè)置為數(shù)字格式,因些增加了Json配置 “ t:chart1_ex ”,例如下代碼:
writer.WritePropertyName("t:chart1_ex");
writer.WriteStartArray();
writer.WriteStartObject();
writer.WritePropertyName("NumberFormat");
writer.WriteValue("#,##0");
writer.WriteEndObject();
writer.WriteEndArray();
為什么用 Json 過渡
我們的云架構(gòu)里設(shè)計(jì)了一個(gè) Office 計(jì)算中心,在某些環(huán)境下,比如 Linux 中需要這種方式傳遞并返回值,以達(dá)到導(dǎo)入導(dǎo)出Office文件的目的。大家可根據(jù)實(shí)際的應(yīng)用進(jìn)行設(shè)計(jì),這里僅作為參考。
開發(fā)環(huán)境
操作系統(tǒng):Windows Server 2019 DataCenter
開發(fā)工具:VisualStudio2019
框架及語言:.net 4.7.1 C#
服務(wù)上需要安裝 Office 2016或以上
關(guān)鍵代碼實(shí)現(xiàn)
假設(shè)文件模板中的散點(diǎn)圖表如下,關(guān)鍵查找字(圖表標(biāo)題)設(shè)為 “ t:chart1”,如下圖:

(1)創(chuàng)建Json格式
這里引入 Newtonsoft.Json.dll 程序集進(jìn)行操作,代碼如下:
StringWriter sw = new StringWriter();
using (Newtonsoft.Json.JsonWriter writer = new Newtonsoft.Json.JsonTextWriter(sw))
{
writer.Formatting = Newtonsoft.Json.Formatting.Indented;
writer.WriteStartObject();
//t:chart1
writer.WritePropertyName("t:chart1");
writer.WriteStartArray();
//point1
writer.WriteStartObject();
writer.WritePropertyName("y");
writer.WriteValue((int)y);
writer.WritePropertyName("x");
writer.WriteValue((int)x);
writer.WriteEndObject();
writer.WriteStartObject();
writer.WriteEndArray();
writer.WritePropertyName("t:chart1_ex");
writer.WriteStartArray();
writer.WriteStartObject();
writer.WritePropertyName("NumberFormat");
writer.WriteValue("#,##0");
writer.WriteEndObject();
writer.WriteEndArray();
//t:chart1
writer.WriteEndObject();
writer.Flush();
}
sw.Close();
string jsonContent = sw.GetStringBuilder().ToString();(2)查找圖表并設(shè)置單元格數(shù)字格式
本代碼程序只顯示示例片斷,非完整程序,僅供參考:
////一些引用
using Word=Microsoft.Office.Interop.Word;
using Newtonsoft.Json.Linq;
////轉(zhuǎn)換 json 字符串為 json 對(duì)象
Newtonsoft.Json.Linq.JObject jObject = null;
if (jsonContent != "")
{
try
{
jObject = Newtonsoft.Json.Linq.JObject.Parse(jsonContent); //轉(zhuǎn)換為json對(duì)象
}
catch (Exception e)
{
resultReport += "create json object fail.<br>"; //失敗記入調(diào)試報(bào)告
}
}
////初始化 Word 應(yīng)用程序
Word.Application WordApp=new Word.Application();
//創(chuàng)建一個(gè)名為WordDoc的文檔對(duì)象
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對(duì)象
//遍歷 json 對(duì)象
foreach (var item in jObject)
{
string tcmd = item.Key.ToString(); //取關(guān)鍵字
//如果 shape 包含圖表,則繼續(xù)
if (shape.HasChart == Microsoft.Office.Core.MsoTriState.msoTrue)
{
//如果圖表未設(shè)置標(biāo)題,則短路
if (shape.Chart.HasTitle == false)
{
continue;
}
//獲取圖表的title
string _name = shape.Chart.ChartTitle.Text.Trim().ToLower();
if (_name.IndexOf(tcmd) != -1) //如果包含關(guān)鍵字則繼續(xù)
{
//替換掉關(guān)鍵字,保留下來的是真正的標(biāo)題
shape.Chart.ChartTitle.Text = shape.Chart.ChartTitle.Text.Replace(tcmd, "");
//這是一個(gè)玄機(jī),否則會(huì)報(bào)錯(cuò),目前我是這樣的解決,A1:Z100,先賦值為空串
shape.Chart.ChartData.Workbook.Worksheets[1].Range("A1:Z100").Value = "";
//計(jì)算最后的單元格地址
string lastcellAddress = "$" + ((char)(64 + jObject[tcmd][0].Count())).ToString() + "$" + jObject[tcmd].Count().ToString();
//獲得最終地址字串
string sourceDataAddress = "='Sheet1'!$A$1:" + lastcellAddress;
//計(jì)算附加配置,設(shè)置單元格數(shù)字格式字串
string numberFormat = "#,##0.0";
if (jObject[_name + "_ex"] != null)
{
if (jObject[_name + "_ex"][0]["NumberFormat"] != null)
{
numberFormat = jObject[_name + "_ex"][0]["NumberFormat"].ToString();
}
}
//遍歷json對(duì)象節(jié)點(diǎn)里的數(shù)組
for (int i = 0; i < jObject[tcmd].Count(); i++)
{
List<JToken> tokens = jObject[tcmd][i].ToList();
int k = 0;
foreach (JToken jToken in tokens)
{
//為每一個(gè)單元格賦值
string celladdress = ((char)(65 + k)).ToString() + (i + 1).ToString();
//設(shè)置單元格數(shù)字格式
shape.Chart.ChartData.Workbook.Worksheets[1].Range(celladdress).NumberFormat = numberFormat;
shape.Chart.ChartData.Workbook.Worksheets[1].Range(celladdress).Value = jToken.ToArray()[0].ToString();
k++;
}
}
shape.Chart.SetSourceData(sourceDataAddress); //設(shè)置更新圖表的數(shù)據(jù)源
break;
} // index of name
} // has chart
}//foreach tcmd
} //WordDoc.InlineShapes
小結(jié)
圖表數(shù)據(jù)的正確呈現(xiàn)受限于Word的提供能力,需要細(xì)心的測(cè)試、調(diào)試,比如
shape.Chart.ChartData.Workbook.Worksheets[1].Range("A1:Z100").Value = ""; 的初始化,散點(diǎn)圖首列的設(shè)置等。
以上就是C#實(shí)現(xiàn)導(dǎo)出Word圖表通用方法之散點(diǎn)圖的詳細(xì)內(nèi)容,更多關(guān)于C#導(dǎo)出Word圖表的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
使用C#實(shí)現(xiàn)在word中插入頁眉頁腳的方法
這篇文章主要介紹了使用C#實(shí)現(xiàn)在word中插入頁眉頁腳的方法,是操作Word的常見方法,有一定的學(xué)習(xí)借鑒價(jià)值,需要的朋友可以參考下2014-08-08
C#異步迭代IAsyncEnumerable應(yīng)用實(shí)現(xiàn)
IAsyncEnumerable可以來實(shí)現(xiàn)異步迭代,本文就主要介紹了C#異步迭代IAsyncEnumerable應(yīng)用實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-06-06
C#簡易人機(jī)對(duì)抗“石頭剪刀布”游戲的實(shí)現(xiàn)
本文主要介紹了C#簡易人機(jī)對(duì)抗“石頭剪刀布”游戲的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-05-05

