C++ で開発したアプリケーションにおいて、Word 文書のページ余白をプログラムから変更したいという要件に直面することがあります。学術論文の投稿規定に合わせた余白調整、ビジネス文書のレイアウト統一、特定のセクションのみ印刷用の狭い余白を適用するといったケースです。
手動で余白を調整するのは、文書数が多い場合に時間がかかるうえ、設定値の入力ミスも発生しやすくなります。本記事では、C++ から Word 文書のページ余白を変更する方法について解説します。
ページ余白操作の技術的課題
Word 文書のページ余白をプログラムで操作する際には、以下のような技術的課題があります。
余白の単位と測定
Word のページ余白はポイント(pt)単位で管理されています。1 インチは 72 ポイントに相当し、ミリメートルやセンチメートルで指定したい場合は単位変換が必要です。また、余白の値は浮動小数点数で扱われるため、精度管理も重要になります。
セクション単位の管理
Word では余白設定がセクション単位で保持されています。つまり、文書内のセクションごとに異なる余白を設定できます。全セクションに同じ余白を適用する場合は、各セクションを個別に処理する必要があります。
実装アプローチの選択肢
C++ から Word 文書のページ余白を変更する方法としては、以下のような選択肢があります。
| 手法 | メリット | デメリット |
|---|---|---|
| サードパーティライブラリ | Office 不要、組み込みが容易 | ライセンスコストが発生する場合あり |
| COM オートメーション | Office と同等の精度 | Windows 限定、Office 要インストール |
| オープンソースライブラリ | 無償で利用可能 | 機能が限定的、余白操作に対応していない場合あり |
本記事では、外部依存が少なく C++ アプリケーションに直接組み込めるサードパーティライブラリを用いる手法について、Spire.Doc for C++ を具体例として実装方法を示します。
環境構築
入手方法
Spire.Doc for C++ は、以下のいずれかの方法でプロジェクトに導入できます。
-
NuGet パッケージマネージャー経由
Visual Studio の「NuGet パッケージの管理」からSpire.Doc.Cppを検索してインストール -
手動での組み込み
配布パッケージを入手し、インクルードディレクトリとライブラリファイルをプロジェクトに追加
評価目的であれば、一時ライセンスを申請することで機能制限なく試用できます。
必要なインクルード
#include "Spire.Doc.o.h"
using namespace Spire::Doc;
using namespace std;
基本的な操作
文書全体の余白を設定する
MarginsF クラスには SetTop、SetBottom、SetLeft、SetRight の各メソッドが用意されており、上下左右の余白を個別に設定できます。以下の例では、上下 72 ポイント(約 2.54 cm)、左右 54 ポイント(約 1.9 cm)に設定しています。
#include "Spire.Doc.o.h"
using namespace Spire::Doc;
using namespace std;
int main()
{
// 入出力ファイルのパスを指定
wstring inputFile = L"Sample.docx";
wstring outputFile = L"SetMargins.docx";
// Document オブジェクトを生成
intrusive_ptr<Document> document = new Document();
// Word 文書を読み込み
document->LoadFromFile(inputFile.c_str());
// 最初のセクションを取得
intrusive_ptr<Section> section = document->GetSections()->GetItemInSectionCollection(0);
// ページ余白を設定(単位:ポイント)
section->GetPageSetup()->GetMargins()->SetTop(72.0f);
section->GetPageSetup()->GetMargins()->SetBottom(72.0f);
section->GetPageSetup()->GetMargins()->SetLeft(54.0f);
section->GetPageSetup()->GetMargins()->SetRight(54.0f);
// 結果を保存
document->SaveToFile(outputFile.c_str(), FileFormat::Docx2013);
document->Close();
return 0;
}
上記のコードでは以下の処理を行っています。
-
Documentオブジェクトを生成し、文書を読み込み -
GetSections()->GetItemInSectionCollection(0)で最初のセクションを取得 -
GetPageSetup()->GetMargins()で余白オブジェクトを取得し、各メソッドで値を設定 -
SaveToFileで結果を保存
ミリメートル単位で余白を設定する
実務ではミリメートル単位で余白を指定したいケースが多いため、以下のような変換関数を用意すると便利です。
// ミリメートルをポイントに変換(1mm ≒ 2.835pt)
float MmToPoints(float mm)
{
return mm * 2.835f;
}
int main()
{
wstring inputFile = L"Sample.docx";
wstring outputFile = L"SetMargins_mm.docx";
intrusive_ptr<Document> document = new Document();
document->LoadFromFile(inputFile.c_str());
intrusive_ptr<Section> section = document->GetSections()->GetItemInSectionCollection(0);
// 上下 25.4mm、左右 19.05mm に設定
section->GetPageSetup()->GetMargins()->SetTop(MmToPoints(25.4f));
section->GetPageSetup()->GetMargins()->SetBottom(MmToPoints(25.4f));
section->GetPageSetup()->GetMargins()->SetLeft(MmToPoints(19.05f));
section->GetPageSetup()->GetMargins()->SetRight(MmToPoints(19.05f));
document->SaveToFile(outputFile.c_str(), FileFormat::Docx2013);
document->Close();
return 0;
}
応用的な操作
すべてのセクションの余白を一括変更する
文書内に複数のセクションが存在する場合、すべてのセクションに対して同じ余白を適用したいことがあります。以下のコードでは、全セクションをループ処理で統一した余白に設定します。
#include "Spire.Doc.o.h"
using namespace Spire::Doc;
using namespace std;
int main()
{
wstring inputFile = L"MultiSection.docx";
wstring outputFile = L"AllSectionsMargins.docx";
intrusive_ptr<Document> document = new Document();
document->LoadFromFile(inputFile.c_str());
// 全セクションの余白を一括設定
int sectionCount = document->GetSections()->GetCount();
for (int i = 0; i < sectionCount; i++)
{
intrusive_ptr<Section> section = document->GetSections()->GetItemInSectionCollection(i);
section->GetPageSetup()->GetMargins()->SetTop(72.0f);
section->GetPageSetup()->GetMargins()->SetBottom(72.0f);
section->GetPageSetup()->GetMargins()->SetLeft(54.0f);
section->GetPageSetup()->GetMargins()->SetRight(54.0f);
}
document->SaveToFile(outputFile.c_str(), FileFormat::Docx2013);
document->Close();
return 0;
}
この方法により、セクションごとに異なる余白が設定されていた文書も、一度の処理で統一できます。
特定のセクションのみ余白を変更する
文書の特定のセクション(例:表紙や付録)だけ異なる余白を設定したい場合は、セクションのインデックスを指定して個別に処理します。
// 2 番目のセクション(インデックス 1)のみ異なる余白を設定
intrusive_ptr<Section> targetSection = document->GetSections()->GetItemInSectionCollection(1);
targetSection->GetPageSetup()->GetMargins()->SetTop(36.0f);
targetSection->GetPageSetup()->GetMargins()->SetBottom(36.0f);
targetSection->GetPageSetup()->GetMargins()->SetLeft(36.0f);
targetSection->GetPageSetup()->GetMargins()->SetRight(36.0f);
現在の余白設定を取得する
既存の文書の余白設定を取得し、それを基準に調整することも可能です。
// 現在の余白を取得
float currentTop = section->GetPageSetup()->GetMargins()->GetTop();
float currentBottom = section->GetPageSetup()->GetMargins()->GetBottom();
float currentLeft = section->GetPageSetup()->GetMargins()->GetLeft();
float currentRight = section->GetPageSetup()->GetMargins()->GetRight();
std::wcout << L"現在の余白設定:" << std::endl;
std::wcout << L" 上: " << currentTop << L" pt" << std::endl;
std::wcout << L" 下: " << currentBottom << L" pt" << std::endl;
std::wcout << L" 左: " << currentLeft << L" pt" << std::endl;
std::wcout << L" 右: " << currentRight << L" pt" << std::endl;
注意点と制限事項
単位について
SetTop、SetBottom、SetLeft、SetRight メソッドの引数はポイント(pt)単位です。ミリメートルやセンチメートルで指定する場合は、適切な単位変換を行ってください。一般的な換算値は以下の通りです。
- 1 インチ = 72 ポイント
- 1 センチメートル ≈ 28.35 ポイント
- 1 ミリメートル ≈ 2.835 ポイント
動作環境
- プラットフォーム: Windows、Linux に対応
- アーキテクチャ: 64 ビットアプリケーション向け
- Microsoft Office: 不要(ライブラリ単体で動作)
メモリ管理
このライブラリでは intrusive_ptr という参照カウント方式のスマートポインタが使用されています。new で生成したオブジェクトは自動的に管理されるため、明示的な delete は不要です。処理完了時には Close() を呼び出してリソースを解放します。
評価版の制限
評価版では、生成される文書に評価版であることを示す透かしが挿入されます。本番環境で使用する場合はライセンスの適用が必要です。
おわりに
本記事では、C++ 環境において Word 文書のページ余白を変更する手法として、Spire.Doc for C++ を用いた実装例を示した。MarginsF クラスの各メソッドを使用することで、上下左右の余白を個別に設定でき、全セクション一括変更やセクションごとの個別設定にも対応できる。
ページ余白の調整は、文書レイアウトの基本設定であり、学術論文やビジネス文書の作成において頻繁に必要となる操作である。実際の開発においては、対象文書のセクション構造を把握した上で、プロジェクトの要件に応じた方法を選択されたい。