【C#】Wordファイルにある表の値をC#のグラフに表示させるには

この記事では、Wordファイルにある表の値をC#のグラフに表示させる方法についてご説明します。

【動画】Wordファイルにある表の値をC#のグラフに表示させる実際の動き

本題に入る前に、まずは次の動画をご覧ください。


Wordアプリケーションのインスタンスを生成し、Wordファイルを開きます。

Wordファイルを開いたら、Wordファイル内にある表のデータを取得し、グラフに表示させます。

参照設定が必要

今回のコードを実行するのに参照設定が必要です。

今回は以下の参照設定を行います。

  1. Microsoft.Office.Interop.Word(Microsoft.Office.Interop.Word.dll)
  2. System.Windows.Forms.DataVisualization(System.Windows.Forms.DataVisualization.dll)

①Microsoft.Office.Interop.Word(Microsoft.Office.Interop.Word.dll)

Microsoft.Office.Interop.Wordを参照設定すると、Wordファイルに対して様々な操作を行うことができるようになります。

今回はWordファイルから表のデータを取得するので、この参照設定が必要になります。

②System.Windows.Forms.DataVisualization(System.Windows.Forms.DataVisualization.dll)

System.Windows.Forms.DataVisualizationを参照設定すると、グラフの作成や取得したデータのグラフ表示など、グラフに関する様々な操作ができるようになります。

今回はWordファイルから表のデータをグラフ表示させるので、この参照設定が必要になります。

コードの流れ

STEP.1
必要な名前空間をインポートする
必要な名前空間をインポートします。
インポートする名前空間には、Word操作やグラフ描画、設定情報の取得などがあります。
STEP.2
Wordファイルを開く
Wordファイルを開きます。
STEP.3
Wordファイルにある表からデータを取得する
Wordファイルにある表からのデータを取得します。
STEP.4
グラフのインスタンスを生成する
グラフのインスタンスを生成します。
STEP.5
グラフのサイズや位置、チャートエリア、凡例などの基本的な設定を行う
グラフのサイズや位置、チャートエリア、凡例などの基本的な設定を行います。
STEP.6
表から取得したデータをグラフに出力する
表から取得したデータをグラフに出力します。
STEP.7
Wordファイルを閉じる
Wordファイルを閉じます。
STEP.8
COMオブジェクトへの参照を解放する
COMオブジェクトへの参照を解放します。

WordファイルとC#のフォームの例

Wordファイル

今回は下のWordファイルを用意しました。

Wordファイルには表が一つ存在しています。

C#のフォーム

今回は下のC#のフォームを用意しました。

フォームにある「グラフの表示」ボタンをクリックすると、下のとおりWordの表のデータをグラフ表示します。

C#のコード(例)

App.configのコード

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
	<startup>
		<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
	</startup>
	<appSettings>
		<!-- Wordファイルのフルパス -->
		<add key="wdFilePath" value="C:\work\10_勉強\21_C#\0066\0066.docx" />
	
	</appSettings>
</configuration>

注目すべきコード

見て頂きたいのは8行目です。

8行目は、バッチファイルのフルパスを「batFilePath」というキーに設定しているコードです。

「batFilePath」のキーの値をフォーム側のコードが参照して使います。

ちなみに、今回扱うWordファイルは下の画像のファイルです。(C:\work\10_勉強\21_C#\0066\0066.docx)

フォームのコード

using System;
using System.Windows.Forms;
using Microsoft.Office.Interop.Word;
using System.Windows.Forms.DataVisualization.Charting;
using System.Configuration;
using Application = Microsoft.Office.Interop.Word.Application;
using Chart = System.Windows.Forms.DataVisualization.Charting.Chart;
using ChartArea = System.Windows.Forms.DataVisualization.Charting.ChartArea;
using Series = System.Windows.Forms.DataVisualization.Charting.Series;
using Legend = System.Windows.Forms.DataVisualization.Charting.Legend;

namespace wfcs_0066
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            // App.configのappSettingsタグ内に記述した「wdFilePath」のキーの値を取得して変数「wdFilePath」に格納する
            string wdFilePath = ConfigurationManager.AppSettings["wdFilePath"];

            // 指定されたファイルパスのWordファイルからグラフを作成する
            CreateChartFromWordDocument(wdFilePath);
        }

        private void CreateChartFromWordDocument(string wdFilePath)
        {
            // Wordアプリケーションのインスタンスを生成する
            Application wordApp = new Application();
            try
            {
                // Wordファイルを開く
                Document document = wordApp.Documents.Open(wdFilePath);
                try
                {
                    // Wordファイルにある最初の表を取得する
                    Table table = document.Tables[1];

                    // グラフを初期化する
                    Chart chart = InitializeChart();

                    // 表のデータからシリーズを作成し、グラフに追加する
                    PopulateSeriesFromTable(chart, table);

                    // フォームにグラフを追加する
                    this.Controls.Add(chart);
                }
                finally
                {
                    // Wordファイルを閉じる
                    document.Close(false);

                    // Wordファイルのインスタンスのリソースを解放する
                    System.Runtime.InteropServices.Marshal.ReleaseComObject(document);
                }
            }
            finally
            {
                // Wordアプリケーションを終了する
                wordApp.Quit();

                // Wordアプリケーションオブジェクトのリソースを解放する
                System.Runtime.InteropServices.Marshal.ReleaseComObject(wordApp);
            }
        }

        private Chart InitializeChart()
        {
            // グラフ用のインスタンスを生成する
            Chart chart = new Chart
            {
                // グラフの縦と横の幅を設定する(横幅・縦幅)
                Size = new System.Drawing.Size(700, 300),

                // フォーム上に設置するグラフの位置を設定する(横・縦)
                Location = new System.Drawing.Point(100, 20)
            };

            // チャートエリア用のインスタンスを生成する
            ChartArea chartArea = new ChartArea();

            // グラフにチャートエリアを追加する
            chart.ChartAreas.Add(chartArea);

            // X軸のラベル間隔を設定する
            chartArea.AxisX.LabelStyle.Interval = 0;

            // X軸のラベルのフォントを設定する(ここでは "Arial" フォントのサイズ8を使用)
            chartArea.AxisX.LabelStyle.Font = new System.Drawing.Font("Arial", 8);

            // 凡例用のインスタンスを生成する
            Legend legend = new Legend();

            // 凡例をグラフに追加する
            chart.Legends.Add(new Legend());

            // 設定を施したchartオブジェクトを返す
            return chart;
        }

        private void PopulateSeriesFromTable(Chart chart, Table table)
        {
            // 表から取得した値から削除する空白や制御文字を取得する
            char[] trimChars = new char[] { '\r', '\a', '\n', ' ' };

            // テーブルの列の数だけ処理を繰り返すFor文
            for (int i = 2; i <= table.Columns.Count; i++)
            {
                // 表の列のヘッダー名を取得してseriesNameに格納する(ヘッダー名はtrimCharsの文字をTrimする)
                string seriesName = table.Cell(1, i).Range.Text.Trim(trimChars);

                // シリーズ用のインスタンスを生成する(棒グラフなら棒のことを指す)
                Series series = new Series(seriesName);

                // シリーズのチャートタイプを設定する
                series.ChartType = SeriesChartType.Column;

                // シリーズのポイント幅を設定する
                series["PointWidth"] = "0.8";

                // シリーズをチャートに追加する
                chart.Series.Add(series);

                // テーブルの行の数だけ処理を繰り返すFor文
                for (int j = 2; j <= table.Rows.Count; j++)
                {
                    // 表の値を取得する(表の値はtrimCharsの文字をTrimする)
                    string cellText = table.Cell(j, i).Range.Text.Trim(trimChars);

                    if (int.TryParse(cellText, out int cellValue))
                    {
                        // 表の値が数値の場合

                        // 棒グラフの場合に棒グラフの棒を追加する
                        series.Points.AddXY(table.Cell(j, 1).Range.Text.Trim(trimChars), cellValue);
                    }
                    else
                    {
                        // 表の値が数値ではないの場合

                        // 数値に変換できない旨のメッセージをコンソールに出力する
                        Console.WriteLine($"数値に変換できない値が検出されました: {cellText}");
                    }
                }
            }
        }
    }
}

注目すべきコード①

最初に見て頂きたいのは1行目から10行目です。

using System;
using System.Windows.Forms;
using Microsoft.Office.Interop.Word;
using System.Windows.Forms.DataVisualization.Charting;
using System.Configuration;
using Application = Microsoft.Office.Interop.Word.Application;
using Chart = System.Windows.Forms.DataVisualization.Charting.Chart;
using ChartArea = System.Windows.Forms.DataVisualization.Charting.ChartArea;
using Series = System.Windows.Forms.DataVisualization.Charting.Series;
using Legend = System.Windows.Forms.DataVisualization.Charting.Legend;

コードの説明

以上のコードは、必要な名前空間の使用宣言およびエイリアス宣言のコードです。

コードの詳細

1行目は、.NET Frameworkの基本クラスのセットを参照する名前空間です。

2行目は、ウィンドウやダイアログボックスを使う名前空間です。

3行目は、Word 文書の作成、編集、保存などがプログラムから行えるようになる名前空間です。

4行目は、チャートやグラフを作成し、表示するためのクラスとコントロールを提供する名前空間です。

5行目は、アプリケーションの実行時設定やカスタム設定を読み込み、保存することができる名前空間です。

アプリケーションの設定をapp.configのような外部の設定ファイルに分けることができ、コンパイルの必要が無く設定値を変更することができるようになります。

6行目は、Microsoft.Office.Interop.Word.Applicationクラスに対してApplicationという名前を定義しています。

7行目は、System.Windows.Forms.DataVisualization.Charting.Chartクラスに対してChartという名前を定義しています。

8行目は、 System.Windows.Forms.DataVisualization.Charting.ChartAreaクラスに対してChartAreaという名前を定義しています。

9行目は、 System.Windows.Forms.DataVisualization.Charting.Seriesクラスに対してSeriesという名前を定義しています。

10行目は、System.Windows.Forms.DataVisualization.Charting.Legendクラスに対してLegendという名前を定義しています。

注目すべきコード②

次に見て頂きたいのは24行目です。

            // App.configのappSettingsタグ内に記述した「wdFilePath」のキーの値を取得して変数「wdFilePath」に格納する
            string wdFilePath = ConfigurationManager.AppSettings["wdFilePath"];

コードの説明

以上のコードは、App.configのappSettingsタグ内に記述した「wdFilePath」のキーの値を取得して変数に格納するコードです。

「wdFilePath」のキーの値は変数「wdFilePath」に格納します。

注目すべきコード③

次に見て頂きたいのは27行目です。

            // 指定されたファイルパスのWordファイルからグラフを作成する
            CreateChartFromWordDocument(wdFilePath);

コードの説明

以上のコードは、指定されたファイルパスのWordファイルからグラフを作成する処理を行うメソッドCreateChartFromWordDocumentを呼び出すコードです。

CreateChartFromWordDocumentが何行目にあるのかというと30行目にあります。

        private void CreateChartFromWordDocument(string wdFilePath)

CreateChartFromWordDocumentを呼び出す際はWordファイルを引数に渡します。

注目すべきコード④

次に見て頂きたいのは30行目です。

        private void CreateChartFromWordDocument(string wdFilePath)

コードの説明

以上のコードは、指定されたファイルパスのWordファイルからグラフを作成する処理を行うメソッドCreateChartFromWordDocumentの宣言のコードです。

CreateChartFromWordDocumentの引数wdFilePathはWordファイル用の引数です。

注目すべきコード⑤

次に見て頂きたいのは33行目です。

            // Wordアプリケーションのインスタンスを生成する
            Application wordApp = new Application();

コードの説明

以上のコードは、Wordアプリケーションのインスタンスを生成するコードです。

このインスタンスを生成することで、Wordの操作(Wordファイルを開く、閉じるなど)を行うことができるようになります。

注目すべきコード⑥

次に見て頂きたいのは34行目から68行目です。

            try
            {
                // Wordファイルを開く
                Document document = wordApp.Documents.Open(wdFilePath);
                try
                {
                    // Wordファイルにある最初の表を取得する
                    Table table = document.Tables[1];

                    // グラフを初期化する
                    Chart chart = InitializeChart();

                    // 表のデータからシリーズを作成し、グラフに追加する
                    PopulateSeriesFromTable(chart, table);

                    // フォームにグラフを追加する
                    this.Controls.Add(chart);
                }
                finally
                {
                    // Wordファイルを閉じる
                    document.Close(false);

                    // Wordファイルのインスタンスのリソースを解放する
                    System.Runtime.InteropServices.Marshal.ReleaseComObject(document);
                }
            }
            finally
            {
                // Wordアプリケーションを終了する
                wordApp.Quit();

                // Wordアプリケーションオブジェクトのリソースを解放する
                System.Runtime.InteropServices.Marshal.ReleaseComObject(wordApp);
            }

コードの説明

以上のコードは、Wordファイルの表のデータを開き、InitializeChartメソッド(使用するグラフを初期化するメソッド)とPopulateSeriesFromTableメソッド(Wordファイルの表のデータをグラフに出力するメソッド)、を呼び出す処理のコードです。

また、PopulateSeriesFromTableメソッドの処理が終了すると、WordファイルとWordアプリケーションを閉じてWordファイルとWordアプリケーションのインスタンスのリソース解放まで行います。

コードの詳細

37行目のコードでは、OpenメソッドにWordファイルのフルパスを指定して実行し、Wordファイルを開きます。

41行目のコードでは、Wordファイルに存在する(上から数えて)1つ目の表のデータを取得してtableに格納します。

44行目のコードは、使用するグラフを初期化するInitializeChartメソッドを呼び出すコードです。

InitializeChartメソッドが何行目にあるのかというと71行目にあります。

        private Chart InitializeChart()

47行目のコードでは、Wordファイルの表のデータをグラフに出力するメソッドPopulateSeriesFromTableを呼び出すコードです。

PopulateSeriesFromTableメソッドが何行目にあるのかというと105行目にあります。

        private void PopulateSeriesFromTable(Chart chart, Table table)

PopulateSeriesFromTableメソッドを呼び出す際は初期化したグラフ用のインスタンスとWordの表のデータを引数に渡します。

50行目のコードでは、フォームにグラフを追加します。

55行目のコードでは、Wordファイルを閉じます。

58行目のコードでは、Wordファイルのインスタンスのリソースを解放します。

64行目のコードでは、Wordアプリケーションを終了します。

67行目のコードでは、Wordアプリケーションオブジェクトのリソースを解放します。

注目すべきコード⑦

次に見て頂きたいのは71行目から103行目です。

        private Chart InitializeChart()
        {
            // グラフ用のインスタンスを生成する
            Chart chart = new Chart
            {
                // グラフの縦と横の幅を設定する(横幅・縦幅)
                Size = new System.Drawing.Size(700, 300),

                // フォーム上に設置するグラフの位置を設定する(横・縦)
                Location = new System.Drawing.Point(100, 20)
            };

            // チャートエリア用のインスタンスを生成する
            ChartArea chartArea = new ChartArea();

            // グラフにチャートエリアを追加する
            chart.ChartAreas.Add(chartArea);

            // X軸のラベル間隔を設定する
            chartArea.AxisX.LabelStyle.Interval = 0;

            // X軸のラベルのフォントを設定する(ここでは "Arial" フォントのサイズ8を使用)
            chartArea.AxisX.LabelStyle.Font = new System.Drawing.Font("Arial", 8);

            // 凡例用のインスタンスを生成する
            Legend legend = new Legend();

            // 凡例をグラフに追加する
            chart.Legends.Add(new Legend());

            // 設定を施したchartオブジェクトを返す。これにより、このメソッドを呼び出した箇所でグラフを利用できるようになる
            return chart;
        }

コードの説明

以上のコードは、Wordファイルの表のデータをグラフに出力・表示させる処理のコードです。

コードの詳細

74行目のコードでは、グラフ用のインスタンスを生成し、グラフの横幅と縦幅(77行目)、設置する位置(縦・横)(80行目)を設定します。

84行目のコードではチャートエリア用のインスタンスを生成し、87行目でグラフにチャートエリアを追加します。

90行目のコードでは、X軸のラベル間隔を設定します。

0を設定すると、X軸のラベルをすべて表示させます。(ただし、データ件数次第(多い場合)で何件か表示されない場合があります)

93行目のコードでは、X軸のラベルのフォントを設定する(ここでは「Arial」フォントのサイズ8を使用しています)

96行目のコードでは凡例用のインスタンスを生成し、99行目のコードで凡例をグラフに追加します。

102行目のコードでは、各設定したchartオブジェクトを返します。

この処理により、このメソッドを呼び出したところでグラフを使うことができるようになります。

注目すべきコード⑧

次に見て頂きたいのは105行目です。

        private void PopulateSeriesFromTable(Chart chart, Table table)

コードの説明

以上のコードは、Wordファイルの表のデータをグラフに出力するメソッドPopulateSeriesFromTableの宣言のコードです。

PopulateSeriesFromTableメソッドには2つ引数があり、chartはグラフ用のインスタンス、TableはWordファイルの表のデータです。

注目すべきコード⑨

次に見て頂きたいのは108行目です。

            // 表から取得した値から削除する空白や制御文字を取得する
            char[] trimChars = new char[] { '\r', '\a', '\n', ' ' };

コードの説明

以上のコードは、表から取得した値から削除する空白や制御文字を取得するコードです。

表から取得した値に余計な文字、例えば空白や制御文字が含まれる場合があるので、その余計な文字を削除するために、trimCharsに余計な文字を格納しておきます。

このtrimCharsは表から取得した時に使います。

注目すべきコード⑩

次に見て頂きたいのは111行目です。

            // テーブルの列の数だけ処理を繰り返すFor文
            for (int i = 2; i <= table.Columns.Count; i++)
            {
                // 表の列のヘッダー名を取得してseriesNameに格納する(ヘッダー名はtrimCharsの文字をTrimする)
                string seriesName = table.Cell(1, i).Range.Text.Trim(trimChars);

                // シリーズ用のインスタンスを生成する(棒グラフなら棒のことを指す)
                Series series = new Series(seriesName);

                // シリーズのチャートタイプを設定する
                series.ChartType = SeriesChartType.Column;

                // シリーズのポイント幅を設定する
                series["PointWidth"] = "0.8";

                // シリーズをチャートに追加する
                chart.Series.Add(series);

                // テーブルの行の数だけ処理を繰り返すFor文
                for (int j = 2; j <= table.Rows.Count; j++)
                {
                    // 表の値を取得する(表の値はtrimCharsの文字をTrimする)
                    string cellText = table.Cell(j, i).Range.Text.Trim(trimChars);

                    if (int.TryParse(cellText, out int cellValue))
                    {
                        // セルの値が数値の場合

                        // 棒グラフの場合に棒グラフの棒を追加する
                        series.Points.AddXY(table.Cell(j, 1).Range.Text.Trim(trimChars), cellValue);
                    }
                    else
                    {
                        // 表の値が数値ではないの場合

                        // 数値に変換できない旨のメッセージをコンソールに出力する
                        Console.WriteLine($"数値に変換できない値が検出されました: {cellText}");
                    }
                }
            }

コードの説明

以上のコードは、Wordファイルの表のデータをグラフに追加する処理のコードです。

コードの詳細

111行目のコードは、テーブルの列の数だけ処理を繰り返すFor文です。

今回は以下のWordファイルの表の値をグラフに出力しますが、2列目から7列目までを対象に6回ループさせます。(1列目は地域名なのでグラフへの出力の対象外としています)

114行目のコードでは、表の列のヘッダー名を取得してseriesNameに格納します。

なお、取得した表の列のヘッダー名に対し、空白や制御文字が含まれている場合に削除するため、Trim関数を実行します。

117行目のコードでは、シリーズ用のインスタンスを生成します。

120行目のコードでは、シリーズのチャートタイプを設定します。

123行目のコードでは、シリーズのポイント幅を設定します。

126行目のコードでは、シリーズをチャートに追加します。

129行目のコードは、テーブルの行の数だけ処理を繰り返すFor文です。

Wordの表の1行目はヘッダ行なので、1行目は対象外とするためカウンタ(変数j)の初期値に2を指定しています。

132行目のコードでは、表の値を取得します。

134行目のコードは、取得した値が数値型かどうかを判定するIF文です。

数値をグラフに表示させるので、Wordの表の値が数値か数値以外なのかをこのIF文で判定します。

数値の場合は139行目で、グラフの棒を追加します。

数値以外の場合は146行目で数値に変換できない旨のメッセージをコンソールに出力します。

動作確認

WordファイルとC#のフォームの例」をご覧ください。

最後に

この記事では、Wordファイルにある表の値をC#のグラフに表示させる方法についてご説明しました。

Wordファイルにある表の値をC#のグラフに表示させたい場合は本記事を参考にして頂けたら幸いです。

プログラミングのスキルを習得するなら

プログラミングのスキルを習得したい、今のスキルをもっと高めたい、そう考えているなら「プログラミングスクール」がおすすめです。

プログラミングのスキルの基礎を身につけるなら「TechAcademy」で1週間の無料体験があるので、これで「プログラミングの基礎」を学ぶのにおすすめですよ。

→ TechAcademyの「1週間 無料体験」はこちら