[C#]Word課題採点システム:Wordファイルからの正確な採点を実現する
情報系授業を受け持っていると、学生から提出された課題の添削がなかなか大変なものです。フィードバックに時間がかかりすぎるのはあまりよくありません。そんなわけで自動採点システムの簡易版をつくってみました。
システムの概要
このシステムは、正解となるWordファイルから情報を抽出し、それを基に学生から提出されたファイルを採点します。まず、正解ファイルをJson形式に変換するためのWordToJsonConverterクラスが用意されています。これにより、正解ファイル内の値や文字列、書式などの情報が抽出され、Jsonファイルとして保存されます。 次に、学生から提出されたファイルを採点するためのWordGraderクラスが存在します。このクラスでは、学生の提出ファイルを解析し、正解との比較を行って採点を行います。採点は、正解となるJsonファイルに記載されたテストケースと学生の提出ファイルの内容を照合して行われます。
実行環境
今回紹介するプログラムは次の環境で開発しました。
開発環境: Microsoft Visual Studio Community 2019
オペレーティングシステム: Windows 10
オフィススイート: Microsoft Office Home and Business 2019
Jsonファイルのフォーマットと構造
このプログラムでは正解を判断するためにJsonファイルに採点基準となるデータをまとめています。
Jsonファイルはテストケース情報を保持するためのファイル形式です。
フォーマットは、データのキーと値がペアとなるキーバリューペア(Key-Value Pair)形式です。
テストケース情報は、正解ファイルから抽出した条件や要素がテストケースごとに記述されます。
各テストケースは、オブジェクト形式で表現され、複数のプロパティが含まれます。
テストケースのプロパティには、以下のような情報が含まれます:
Name: テストケース名
Alignment: テキストの配置(Left, Center, Right)
Value: 値(条件に応じたテストケースの値)
Font: フォント情報(Name, Size, Bold, Italic, Underline)
Presence: 要素の存在の有無(Exists, NotExists)
Page: テストケースが適用されるページ
Line: テストケースの行番号
Text: テストケースのテキスト
EndTextBox: テキストボックスの終了の有無
NotLastPageEmpty: 最終ページが空でないことの有無
PageLayout: ページのレイアウト(Narrow, Normal)
以上がJsonファイルのフォーマットと構造に関する情報です。この形式を利用して、正解ファイルから抽出したテストケース情報をJsonファイルとして保存し、後の採点プロセスで使用します。
ライブラリの準備
Microsoft Office Interopを導入
Microsoft Office Interopは、Microsoft Office製品(Word、Excel、PowerPointなど)と外部のプログラム(通常は.NETベースのプログラミング言語を使用)との間で相互作用するための技術およびライブラリのセットです。
Microsoft Office Interopは、外部のプログラムがOffice製品の機能にアクセスし、データを操作、生成、変換することを可能にします。これにより、プログラムがOffice製品の機能を活用して、テキスト文書の作成や編集、スプレッドシートの操作、プレゼンテーションの作成などのタスクを自動化することができます。
具体的には、Interopを使用することで、外部プログラムからOfficeアプリケーションを起動したり、ドキュメントやワークブックを開いたり、データの読み取りや書き込み、スタイルの設定、グラフの作成などの操作を行うことができます。また、Interopを使用することで、Office製品との間でデータの相互変換も可能です。
ただし、注意点として、InteropはOffice製品との密接な統合を提供するものですが、パフォーマンスや互換性の問題があることがあります。また、Interopを使用する場合、コンピュータにOffice製品がインストールされている必要があります。
それでは導入手順をお話しします。Visual Studioを開きます。ソリューションエクスプローラーでプロジェクトを右クリックし、「NuGet パッケージの管理」をクリックします。
「参照」タブを選択し、「Microsoft.Office.Interop.Word」を検索します。
検索結果から「Microsoft.Office.Interop.Word」を選択し、「インストール」をクリックします。
インストールが完了したら、プロジェクトに「using Microsoft.Office.Interop.Word;」というコードを追加します。これにより、プロジェクトでMicrosoft Office Interopが使用可能になります。
Newtonsoft.Jsonを導入
Newtonsoft.Jsonは、.NETのJSON処理ライブラリであり、NuGetパッケージマネージャを通じてプロジェクトに追加する必要があります。
以下に、Visual StudioでNuGetパッケージを使用してNewtonsoft.Jsonをインストールする手順を示します。
NuGetパッケージマネージャを開く: ソリューションエクスプローラーで対象のプロジェクトを右クリックし、「NuGetパッケージの管理」を選択します。
パッケージを探す: パッケージマネージャータブで「参照」を選択し、検索ボックスにNewtonsoft.Jsonと入力します。
パッケージをインストール: 検索結果からNewtonsoft.Jsonを選択し、「インストール」ボタンをクリックします。
インストールの確認: パッケージをプロジェクトに追加することを確認するダイアログが表示されるので、「OK」をクリックします。
変更の保存: インストールが完了したら、Visual Studioでプロジェクトの変更を保存します。
各ソースコードの概要
Font.cs
フォント情報を表すクラスです。
他のクラスでフォント情報が使用されるため、先に説明することで後続の解説が分かりやすくなります。
TestCase.cs
テストケース情報を表すクラスです。
フォント情報を含むなど、テストケースに関連する重要な情報が含まれています。
WordToJsonConverter.cs
WordファイルをJsonファイルに変換するためのクラスです。
テストケース情報の抽出とJson形式への変換が行われます。
WordGrader.cs
Wordファイルの採点を行うためのクラスです。
学生の提出ファイルと正解のテストケース情報を比較して採点を行います。
MainForm.cs(フォーム)
メインフォームのクラスです。
フォーム上のボタン操作に応じて、Wordファイルの変換や採点の処理が呼び出されます。
それでは個別のファイルについて説明します。
各ソースの詳細
Font.cs:フォントクラス
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WordDocGrader
{
public class Font
{
public string Name { get; set; }
public float Size { get; set; }
public bool Bold { get; set; }
public bool Italic { get; set; }
public bool Underline { get; set; }
}
}
「Font.cs」は、Word課題採点システムにおいて、フォントの情報を表現するためのクラスです。
フォントは、文字の見た目やスタイルを決める要素であり、例えば文字の大きさや太さ、斜体や下線の有無などがフォントの情報に含まれます。
「Font.cs」では、以下のようなプロパティが定義されています。
Name(フォント名) 文字のスタイルに使用するフォントの名前が格納されます。例えば、「メイリオ」や「Arial」などのフォント名を指定することができます。
Size(文字の大きさ) 文字のサイズを表す数値が格納されます。この値は、ポイント(pt)という単位で指定します。例えば、「12」や「16」などの数値を指定することができます。
Bold(太字の有無) 文字を太字で表示するかどうかを示す論理値(true/false)が格納されます。文字を太字にする場合は「true」を、太字でない場合は「false」を指定します。
Italic(斜体の有無) 文字を斜体で表示するかどうかを示す論理値(true/false)が格納されます。文字を斜体にする場合は「true」を、斜体でない場合は「false」を指定します。
Underline(下線の有無) 文字に下線を引くかどうかを示す論理値(true/false)が格納されます。文字に下線を引く場合は「true」を、引かない場合は「false」を指定します。
「Font.cs」は、Wordファイルの正解ファイルや学生の提出ファイルにおける文字のフォント情報を表現するために使用されます。採点の際に、正解と一致するフォント情報を持つテキストを判定するために利用されます。
フォントの情報は、見た目やスタイルの一貫性を確認したり、採点基準として使用するために重要です。
TestCase.cs:テストケースクラス
「TestCase.cs」は、Word課題採点システムにおいて、テストケースの情報を表現するためのクラスです。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WordDocGrader
{
public class TestCase
{
public string Name { get; set; }
public string Alignment { get; set; }
public string Value { get; set; }
public Font Font { get; set; }
public string Presence { get; set; }
public string Page { get; set; }
public bool LastPageEmpty { get; set; }
public string Margin { get; set; }
public string TextBoxPresence { get; set; }
public int? Line { get; set; }
public string Text { get; set; }
public bool? EndTextBox { get; set; }
public bool? NotLastPageEmpty { get; set; }
public string PageLayout { get; set; }
}
}
テストケースとは、採点の際に比較や判定を行うための基準となる条件や要素のことです。例えば、特定の行に特定の文字列が存在するかどうかや、テキストの配置やフォントのスタイルなどがテストケースとして設定されます。
「TestCase.cs」では、以下のようなプロパティが定義されています。
Name(テストケース名) テストケースを識別するための名前が格納されます。例えば、「テキストが正しく配置されているか」や「フォントが一致するか」といったテストケース名を指定することができます。
Alignment(配置) テキストの配置(左揃え、中央揃え、右揃え)が格納されます。例えば、「Left(左揃え)」や「Center(中央揃え)」、「Right(右揃え)」を指定することができます。
Value(値) テストケースの条件となる値が格納されます。例えば、「特定の行に存在する文字列」や「指定の値と一致するか」といった条件に使用されます。
Font(フォント情報) テストケースに関連するフォントの情報が格納されます。先ほど説明した「Font.cs」クラスを利用して、フォントの名前、サイズ、太字や斜体、下線の有無などを指定することができます。
Presence(存在の有無) テストケースの条件となる要素(テキストやフォントなど)が存在するかどうかを示す文字列が格納されます。例えば、「Exists(存在する)」や「NotExists(存在しない)」を指定することができます。
Page(ページ) テストケースが適用されるページの情報が格納されます。例えば、「1ページ目」や「最終ページ」を指定することができます。
なお、上記以外にもさまざまなプロパティが存在しますが、初心者の方にも分かりやすくするために、ここでは主要なプロパティを説明しました。
「TestCase.cs」は、Wordファイルの正解ファイルや学生の提出ファイルにおけるテストケースの情報を表現するために使用されます。採点の際に、各テストケースの条件と一致するかどうかを判定し、採点結果を決定するために利用されます。
テストケースは、正解となる条件や要素を明確にするために重要な役割を果たします。
WordToJsonConverter.cs:WordからJsonへの変換クラス
using Microsoft.Office.Core;
using Microsoft.Office.Interop.Word;
using Newtonsoft.Json;
using System.Collections.Generic;
using System.IO;
namespace WordDocGrader
{
public class WordToJsonConverter
{
public void Convert(string wordFilePath, string jsonFilePath)
{
var application = new Application();
var document = application.Documents.Open(wordFilePath);
var testCases = new List<TestCase>();
for (int i = 1; i <= document.Paragraphs.Count; i++)
{
var paragraph = document.Paragraphs[i];
var font = paragraph.Range.Font;
testCases.Add(new TestCase
{
Line = i,
Text = paragraph.Range.Text.Trim(),
Alignment = GetAlignment(paragraph),
Font = new Font
{
Name = font.Name,
Size = font.Size,
Underline = font.Underline != WdUnderline.wdUnderlineNone,
Bold = font.Bold == 1
}
});
}
// Checking for TextBox existence
var hasTextBox = false;
foreach (Microsoft.Office.Interop.Word.Shape shape in document.Shapes)
{
if (shape.Type == MsoShapeType.msoTextBox)
{
hasTextBox = true;
testCases.Add(new TestCase
{
EndTextBox = true,
Text = shape.TextFrame.TextRange.Text
});
break;
}
}
if (!hasTextBox)
{
testCases.Add(new TestCase
{
EndTextBox = false
});
}
// Checking if the last page is not empty
var lastChar = document.Characters.Last;
var endOfDoc = lastChar.get_Information(WdInformation.wdActiveEndPageNumber);
var lastCharPage = lastChar.get_Information(WdInformation.wdActiveEndAdjustedPageNumber);
testCases.Add(new TestCase
{
NotLastPageEmpty = lastCharPage == endOfDoc
});
// Checking for PageLayout
var margins = document.PageSetup;
testCases.Add(new TestCase
{
PageLayout = margins.TopMargin == margins.BottomMargin && margins.LeftMargin == margins.RightMargin ? "Narrow" : "Normal"
});
var json = JsonConvert.SerializeObject(testCases, Formatting.Indented);
File.WriteAllText(jsonFilePath, json);
document.Close();
application.Quit();
}
private string GetAlignment(Paragraph paragraph)
{
switch (paragraph.Alignment)
{
case WdParagraphAlignment.wdAlignParagraphCenter:
return "Center";
case WdParagraphAlignment.wdAlignParagraphRight:
return "Right";
default:
return "Left";
}
}
}
}
「WordToJsonConverter.cs」は、Word課題採点システムにおいて、WordファイルをJsonファイルに変換するためのクラスです。
このクラスでは、正解となるWordファイルから情報を抽出し、それをJson形式に変換して保存します。具体的な動作は以下の通りです。
Convertメソッド
このメソッドは、Wordファイルを受け取り、その内容からテストケース情報を抽出してJsonファイルに変換します。
メソッドの中で行われる処理は、以下のような流れです。
Microsoft.Office.Interop.Wordを使用して、Wordファイルを開く
テストケースのリストを作成する
Wordファイル内の情報を解析し、テストケースごとに条件や要素を取得する
取得した情報を元にテストケースオブジェクトを作成し、テストケースリストに追加する
テストケースリストをJson形式に変換し、Jsonファイルとして保存する
このようにして、Wordファイル内の情報を解析し、テストケース情報を抽出します。抽出された情報は、フォントのスタイル、テキストの配置、テキストボックスの存在など、採点のために重要な情報となります。
テストケース情報はJsonファイルとして保存されるため、後で採点に使用することができます。
「WordToJsonConverter.cs」は、Wordファイルからテストケース情報を抽出し、Json形式に変換するためのクラスです。このクラスを使用することで、正解のWordファイルからテストケース情報を簡単に生成し、採点の基準となるJsonファイルを作成することができます。
WordGrader.cs:Word採点クラス
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace WordDocGrader
{
public class WordGrader
{
public void Grade(string wordFilePath, string jsonFilePath)
{
var application = new Microsoft.Office.Interop.Word.Application();
var document = application.Documents.Open(wordFilePath);
var json = File.ReadAllText(jsonFilePath);
var testCases = JsonConvert.DeserializeObject<List<TestCase>>(json);
int score = 0;
for (int i = 0; i < testCases.Count; i++)
{
var testCase = testCases[i];
if (testCase.Line.HasValue)
{
var paragraph = document.Paragraphs[testCase.Line.Value];
var font = paragraph.Range.Font;
if (paragraph.Range.Text.Trim() == testCase.Text
&& GetAlignment(paragraph) == testCase.Alignment
&& font.Name == testCase.Font.Name
&& font.Size == testCase.Font.Size
&& (font.Underline != Microsoft.Office.Interop.Word.WdUnderline.wdUnderlineNone) == testCase.Font.Underline
&& (font.Bold == 1) == testCase.Font.Bold)
{
score++;
}
}
else if (testCase.EndTextBox.HasValue)
{
bool hasTextBox = false;
foreach (Microsoft.Office.Interop.Word.Shape shape in document.Shapes)
{
if (shape.Type == Microsoft.Office.Core.MsoShapeType.msoTextBox
&& shape.TextFrame.TextRange.Text == testCase.Text)
{
hasTextBox = true;
break;
}
}
if (hasTextBox == testCase.EndTextBox)
{
score++;
}
}
else if (testCase.NotLastPageEmpty.HasValue)
{
var lastChar = document.Characters.Last;
var endOfDoc = lastChar.get_Information(Microsoft.Office.Interop.Word.WdInformation.wdActiveEndPageNumber);
var lastCharPage = lastChar.get_Information(Microsoft.Office.Interop.Word.WdInformation.wdActiveEndAdjustedPageNumber);
if ((lastCharPage == endOfDoc) == testCase.NotLastPageEmpty)
{
score++;
}
}
else if (!string.IsNullOrEmpty(testCase.PageLayout))
{
var margins = document.PageSetup;
string pageLayout = margins.TopMargin == margins.BottomMargin && margins.LeftMargin == margins.RightMargin ? "Narrow" : "Normal";
if (pageLayout == testCase.PageLayout)
{
score++;
}
}
}
Console.WriteLine($"Score: {score} / {testCases.Count}");
document.Close();
application.Quit();
}
private string GetAlignment(Microsoft.Office.Interop.Word.Paragraph paragraph)
{
switch (paragraph.Alignment)
{
case Microsoft.Office.Interop.Word.WdParagraphAlignment.wdAlignParagraphCenter:
return "Center";
case Microsoft.Office.Interop.Word.WdParagraphAlignment.wdAlignParagraphRight:
return "Right";
default:
return "Left";
}
}
}
}
「WordGrader.cs」は、Word課題採点システムにおいて、Wordファイルの採点を行うためのクラスです。
このクラスでは、学生が提出したWordファイルと正解のテストケース情報を比較し、採点を行います。具体的な動作は以下の通りです。
Gradeメソッド このメソッドは、学生が提出したWordファイルと正解のテストケース情報を受け取り、採点を実行します。
メソッドの中で行われる処理は、以下のような流れです。
Microsoft.Office.Interop.Wordを使用して、Wordファイルを開く
提出されたWordファイルと正解のテストケース情報を読み込む
テストケースごとに条件をチェックし、正解と一致するかどうかを判定する
正解のテストケースと一致した場合、スコアを加算する
最終的なスコアを表示する
このようにして、提出されたWordファイルと正解のテストケース情報を照合し、条件に基づいて採点を行います。テストケースごとに指定された条件に一致するかどうかを判定し、正解と一致した場合にスコアを加算します。
採点結果はスコアとして表示され、学生の課題の正確性や適合性を評価するために使用されます。
注意点としては、このクラスではMicrosoft.Office.Interop.Wordを使用してWordファイルを開くため、Windows環境での動作が前提となります。また、正解のテストケース情報はJsonファイルとして提供される必要があります。
「WordGrader.cs」は、Wordファイルの採点を行うための重要なクラスであり、学生の提出ファイルと正解の基準を比較し、採点結果を算出する役割を果たします。
MainForm.cs:メインフォームクラス
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WordDocGrader
{
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
}
private void ExportJsonButton_Click(object sender, EventArgs e)
{
string basePath = AppDomain.CurrentDomain.BaseDirectory;
// Wordファイルと出力するJSONファイルのパスを指定します
string wordFilePath = Path.Combine(basePath, "..", "..", "ummtFiles", "練習問題3-4_完成.docx");
string jsonFilePath = Path.Combine(basePath, "..", "..", "ummtFiles", "練習問題3-4.json");
// WordToJsonConverterオブジェクトを作成します
var converter = new WordToJsonConverter();
// Convertメソッドを呼び出してWordファイルからJSONファイルを生成します
converter.Convert(wordFilePath, jsonFilePath);
}
private void GradeAssignmentButton_Click(object sender, EventArgs e)
{
string basePath = AppDomain.CurrentDomain.BaseDirectory;
// WordファイルとJSONファイルのパスを指定します
string wordFilePath = Path.Combine(basePath, "..", "..", "ummtFiles", "練習問題3-4_提出.docx");
string jsonFilePath = Path.Combine(basePath, "..", "..", "ummtFiles", "練習問題3-4.json");
// WordGraderオブジェクトを作成します
var grader = new WordGrader();
// Gradeメソッドを呼び出して採点を行います
grader.Grade(wordFilePath, jsonFilePath);
}
}
}
「MainForm.cs」は、Word課題採点システムのメイン画面を管理するためのクラスです。この画面では、システムの操作を行うためのボタンが配置されています。
画面上には、「ExportJsonButton」と「GradeAssignmentButton」という2つのボタンがあります。それぞれのボタンをクリックすることで、以下の機能が実行されます。
ExportJsonButton(JSONファイルへの変換ボタン) このボタンをクリックすると、Wordの正解ファイルを読み込んでJSONファイルに変換します。具体的には、正解ファイルから値や文字列、書式などの情報を読み取り、それをJSON形式に変換して保存します。これにより、採点のために必要な情報をJSONファイルにまとめることができます。
GradeAssignmentButton(課題の採点ボタン) このボタンをクリックすると、学生が提出した課題ファイルを採点します。まず、正解となるJSONファイルと学生の提出ファイルを読み込みます。そして、それぞれのファイルの内容を比較して採点を行います。テストケースごとに条件をチェックし、正解と一致するかどうかを判定します。採点結果はスコアとして表示されます。
注意点としては、このシステムはWindows環境で動作し、Visual Studioを使ってC#言語で開発されていることです。また、正解ファイルや学生の提出ファイルはWord形式である必要があります。
このように、「MainForm.cs」はシステムのメイン画面を担当し、正解ファイルのJSON変換や学生の課題の採点(ここではコンソール)といった重要な機能を提供しています。
その他の準備
Word課題採点システムを使用する際には、このプログラムの場合は事前に「ummtFiles」というディレクトリを作成する必要があります。このディレクトリは、正解ファイルや提出ファイルのパスを指定するために使用されます。以下の注意事項に従って、正しいディレクトリの作成を行ってください。
「ummtFiles」というディレクトリをプロジェクトのルートディレクトリに作成します。
プロジェクトのルートディレクトリとは、Visual Studioで開いたプロジェクトフォルダのことです。
「ummtFiles」ディレクトリ内に、正解ファイルと提出ファイルを配置してください。
正解ファイルは「練習問題3-4_完成.docx」という名前で保存してください。
提出ファイルは「練習問題3-4_提出.docx」という名前で保存してください。
MainForm.cs内のファイルパス指定部分を確認し、適切なディレクトリ構造とファイル名を指定してください。
ファイルパス指定部分は、「ExportJsonButton_Click」メソッドと「GradeAssignmentButton_Click」メソッド内にあります。
パスの指定方法に注意し、正解ファイルと提出ファイルのパスを正確に指定してください。
以上の注意事項を守って、「ummtFiles」ディレクトリを作成し、正解ファイルと提出ファイルを適切に配置してください。これにより、Word課題採点システムが正常に動作し、採点が行えるようになります。
操作手順
Wordファイルの正解ファイルを準備します。
正解のテストケースを含むWordファイルを用意します。
Visual Studioを起動し、Word課題採点システムのプロジェクトを開きます。
MainForm.csを開きます。
MainForm.csはメインフォームのクラスです。
ExportJsonButtonをクリックします。
正解のWordファイルをJsonファイルに変換します。
WordToJsonConverterクラスが実行され、Wordファイルからテストケース情報が抽出されます。
WordToJsonConverterクラスに指定された正解ファイルのパスを確認します。
正解ファイルのパスは、MainForm.cs内で指定されています。
ファイルパスを必要に応じて変更してください。
Jsonファイルの出力先パスを確認します。
WordToJsonConverterクラスに指定されたJsonファイルのパスを確認します。
ファイルパスを必要に応じて変更してください。
GradeAssignmentButtonをクリックします。
学生から提出されたWordファイルを採点します。
WordGraderクラスが実行され、採点結果が表示されます。
WordGraderクラスに指定された提出ファイルのパスを確認します。
提出ファイルのパスは、MainForm.cs内で指定されています。
ファイルパスを必要に応じて変更してください。
WordGraderクラスに指定されたJsonファイルのパスを確認します。
Jsonファイルのパスは、MainForm.cs内で指定されています。
ファイルパスを必要に応じて変更してください。
採点結果がコンソールに表示されます。
スコアとテストケースの総数が表示され、採点の正確性が評価されます。
以上が、Word課題採点システムの基本的な操作手順です。必要に応じてファイルパスや設定を変更して、正解ファイルと学生の提出ファイルを採点してください。
実行結果
実行したらこのような感じで出力されます。
まとめ
あくまで簡易版なので、用途に応じて採点項目を増やすなり、採点結果をファイル出力するなり、改造できると思います。ご参考になれば幸いです。
この記事が気に入ったらサポートをしてみませんか?