目次
概要
Microsoft Wordがインストールされていない環境(サーバーやLinuxなど)で、.docx 形式のWordファイルを新規作成する実装です。
Microsoftが提供する「OpenXML SDK」を使用し、Word文書の構造(Document, Body, Paragraph, Run, Text)をプログラムから構築してテキストを出力します。
仕様(入出力)
- 入力: 保存先のファイルパス、書き込むテキスト
- 出力:
.docxファイル - ライブラリ: DocumentFormat.OpenXml (NuGetパッケージ)
実装メソッド
| メソッド名 | 説明 |
AppendParagraph | 段落(Paragraph)、書式(Run)、テキスト(Text)を順に作成して追加する基本実装です。 |
AppendParagraph2 | コンストラクタのネストを利用し、1行で簡潔に段落を追加する短縮実装です。 |
基本の使い方
まず、NuGetパッケージをインストールします。
dotnet add package DocumentFormat.OpenXml
実装したクラスの使用例です。
// ファイルパスを指定してインスタンス生成
using var doc = new MyWordDoc("Report.docx");
// 通常のメソッドで書き込み
doc.AppendParagraph("これは最初の段落です。");
// 短縮メソッドで書き込み
doc.AppendParagraph2("これは次の段落です。簡潔に記述できます。");
コード全文
using System;
using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Wordprocessing;
class Program
{
static void Main()
{
string filePath = "Report.docx";
try
{
Console.WriteLine($"Creating Word document: {filePath}");
// usingステートメントで確実にDispose(保存・クローズ)させる
using (var doc = new MyWordDoc(filePath))
{
doc.AppendParagraph("【日報】本日の業務報告");
doc.AppendParagraph("本日はOpenXML SDKの基本実装を行いました。");
doc.AppendParagraph2("進捗は順調です。");
doc.AppendParagraph2("以上、よろしくお願いいたします。");
}
Console.WriteLine("Document created successfully.");
}
catch (Exception ex)
{
Console.WriteLine($"Error: {ex.Message}");
}
}
}
/// <summary>
/// OpenXML SDKを使用したWord文書作成クラス
/// </summary>
public sealed class MyWordDoc : IDisposable
{
private WordprocessingDocument _document;
private Body _body;
// コンストラクタでドキュメント構造を初期化
public MyWordDoc(string filePath)
{
// 1. WordprocessingDocumentを作成(ファイル作成)
_document = WordprocessingDocument.Create(filePath, WordprocessingDocumentType.Document);
// 2. MainDocumentPart(文書の主要部分)を追加
MainDocumentPart mainPart = _document.AddMainDocumentPart();
// 3. Documentツリーを作成
mainPart.Document = new Document();
// 4. Body(本文領域)を作成してDocumentに追加
_body = mainPart.Document.AppendChild(new Body());
}
// 基本的な追加方法(構造が分かりやすい記述)
public void AppendParagraph(string text)
{
// 段落(Paragraph)を作成
Paragraph para = _body.AppendChild(new Paragraph());
// 実行単位(Run)を作成して段落に追加
// ※Runはフォントや色などの書式設定を持つ単位
Run run = para.AppendChild(new Run());
// テキスト(Text)を作成してRunに追加
run.AppendChild(new Text(text));
}
// 簡潔な追加方法(ネストを利用した記述)
public void AppendParagraph2(string text)
{
// Paragraph > Run > Text を一括で生成してBodyに追加
_body.AppendChild(
new Paragraph(
new Run(
new Text(text)
)
)
);
}
// リソースの解放と保存
public void Dispose()
{
// CloseまたはDisposeで変更が保存される
_document?.Dispose();
}
}
カスタムポイント
- スタイルの適用:文字を太字にしたり色を変えたりする場合は、Run オブジェクトに対して RunProperties を設定します。C#
var runProps = new RunProperties(); runProps.Append(new Bold()); // 太字 runProps.Append(new Color() { Val = "FF0000" }); // 赤色 run.RunProperties = runProps; - 改ページの挿入:特定の場所でページを変えたい場合は、Paragraph 内に Break() { Type = BreakValues.Page } を追加します。
注意点
- 階層構造の理解:OpenXMLでは Body > Paragraph > Run > Text という階層構造が厳格に決まっています。Body に直接 Text を追加することはできず、必ずこの入れ子構造を守る必要があります。
- Disposeの必須性:WordprocessingDocument は Dispose()(または Close())が呼ばれたタイミングでXMLデータをファイルに書き込み、保存を完了させます。using 文を使わないと、ファイルが破損したりサイズが0バイトになったりします。
- ファイルアクセスの競合:作成しようとしているファイルがWordで開かれていると、IOException が発生します。実行前に必ず同名のファイルを閉じてください。
応用
テキストの置換機能の実装
テンプレートファイル内の特定の文字列(例: {DATE})を置換して保存する例です。
public void ReplaceText(string placeholder, string value)
{
// 文書内のすべてのテキスト要素を検索
foreach (var text in _body.Descendants<Text>())
{
if (text.Text.Contains(placeholder))
{
text.Text = text.Text.Replace(placeholder, value);
}
}
}
まとめ
OpenXML SDKを使用すれば、Wordアプリケーションに依存することなく、高速かつ安全にドキュメントを生成できます。構造がやや冗長に見えますが、Paragraph(段落)と Run(書式範囲)の関係を理解すれば、メソッドをカプセル化することで直感的に扱えるようになります。
