ワープロ ドキュメントの印刷の向きを変更する
このトピックでは、Open XML SDK for Office のクラスを使用して、Microsoft Word ドキュメントの印刷方向をプログラムで設定する方法について説明します。 このタスクを示すメソッド SetPrintOrientation
例が含まれています。
SetPrintOrientation メソッド
SetPrintOrientation
メソッドを使用して、ワープロ文書の印刷方向を変更できます。 メソッドは、変更するドキュメントの名前 (文字列) と新しい印刷方向 (PageOrientationValues) を示す 2 つのパラメーターを受け入れます。
次のコードは、 SetPrintOrientation
メソッドを示しています。
static void SetPrintOrientation(string fileName, string orientation)
ドキュメントのセクションごとに、新しい印刷方向がセクションの現在の印刷方向と異なる場合は、コードでセクションの印刷方向を変更します。 さらに、このコードでは、各セクションの幅、高さ、および余白を手動で更新する必要があります。
サンプル SetPrintOrientation メソッドの呼び出し
サンプル SetPrintOrientation
メソッドを呼び出すには、変換するファイルの名前と、目的の向きに応じて文字列 "横" または "縦" を含む文字列を渡します。 次のコードは、メソッド呼び出しの例です。
SetPrintOrientation(args[0], args[1]);
コードの動作のしくみ
次のコードでは、最初に適用する方向を決定し、 Open メソッドを使用してドキュメントを開き、 isEditable
パラメーターを true
に設定して、ドキュメントを読み取り/書き込みする必要があることを示します。 コードは、メイン ドキュメント パーツへの参照を取得し、その参照を使用して、ドキュメントのコンテンツ内でSectionProperties型のすべての子孫のコレクションを取得します。 後で、このコレクションを使用して、各セクションの印刷方向を順に設定します。
PageOrientationValues newOrientation = orientation.ToLower() switch
{
"landscape" => PageOrientationValues.Landscape,
"portrait" => PageOrientationValues.Portrait,
_ => throw new System.ArgumentException("Invalid argument: " + orientation)
};
using (var document = WordprocessingDocument.Open(fileName, true))
{
if (document?.MainDocumentPart?.Document.Body is null)
{
throw new ArgumentNullException("MainDocumentPart and/or Body is null.");
}
Body docBody = document.MainDocumentPart.Document.Body;
IEnumerable<SectionProperties> sections = docBody.ChildElements.OfType<SectionProperties>();
if (sections.Count() == 0)
{
docBody.AddChild(new SectionProperties());
sections = docBody.ChildElements.OfType<SectionProperties>();
}
すべてのセクションで反復処理する
次のコード ブロックは、 SectionProperties
要素のコレクション内のすべてのセクションを反復処理します。 セクションごとに、セクションのページの方向が変更されたかどうかを追跡する変数を初期化し、コードでページのサイズと余白を更新できるようにします (新しい方向が元の方向と一致する場合は、ページを更新しません)。 (新しい向きが元の向きと一致する場合、コードはページを更新しません)。コードは、SectionProperties
要素の最初のPageSize子孫への参照を取得することで続行されます。 参照が null でない場合は、必要に応じて方向を更新します。
foreach (SectionProperties sectPr in sections)
{
bool pageOrientationChanged = false;
PageSize pgSz = sectPr.ChildElements.OfType<PageSize>().FirstOrDefault() ?? sectPr.AppendChild(new PageSize() { Width = 12240, Height = 15840 });
セクションの印刷の向きを設定する
次のコード ブロックでは、最初に、PageSize
要素の Orient プロパティが存在するかどうかを確認します。 Open XML 要素のその他の大多数のプロパティと同様に、このプロパティまたは属性はまだ存在しない可能性があります。 その場合、プロパティを取得すると null 参照が返されます。 既定では、プロパティが存在しない場合は、新しい印刷の向きは縦向きで、コードはページを更新しません。
Orient
プロパティが既に存在し、その値が パラメーターとしてメソッドに指定された新しい方向の値と異なる場合、コードは Orient
プロパティの Value
プロパティを設定し、pageOrientationChanged
フラグを設定します。 (コードでは、 pageOrientationChanged
フラグを使用して、ページ サイズと余白を更新する必要があるかどうかを判断します)。
注:
コードで Orient
プロパティを作成する必要がある場合は、プロパティに格納する値も新しい EnumValue<T> インスタンスとして作成し、 EnumValue
コンストラクターに新しい方向を指定する必要があります。
if (pgSz.Orient is null)
{
// Need to create the attribute. You do not need to
// create the Orient property if the property does not
// already exist, and you are setting it to Portrait.
// That is the default value.
if (newOrientation != PageOrientationValues.Portrait)
{
pageOrientationChanged = true;
pgSz.Orient = new EnumValue<PageOrientationValues>(newOrientation);
}
}
else
{
// The Orient property exists, but its value
// is different than the new value.
if (pgSz.Orient.Value != newOrientation)
{
pgSz.Orient.Value = newOrientation;
pageOrientationChanged = true;
}
ページ サイズを更新する
コードのこの時点で、ページの向きが変更されている可能性があります。 その場合、コードはさらに 2 つのタスクを完了する必要があります。 ページ サイズを更新し、セクションのページ余白を更新する必要があります。 最初のタスクは簡単です。次のコードは、ページの高さと幅を入れ替え、値を PageSize
要素に格納するだけです。
if (pageOrientationChanged)
{
// Changing the orientation is not enough. You must also
// change the page size.
var width = pgSz.Width;
var height = pgSz.Height;
pgSz.Width = height;
pgSz.Height = width;
ページの余白を更新する
サンプル プロシージャの次の手順では、セクションの余白を処理します。
ページの向きを変更した場合、コードはそれに合わせてページの余白を回転する必要があります。 これを行うために、コードは セクションの PageMargin 要素への参照を取得します。 要素が存在する場合、コードはページの余白を回転させます。 コードはページの余白を 90 度回転させますが、一部のプリンターでは 270 度回転させるため、これを考慮してコードを修正する必要があります。
また、PageMargin
オブジェクトのTopプロパティとBottomプロパティは符号付き値であり、LeftプロパティとRightプロパティは符号なし値であることに注意してください。 次のコードに示すように、コードは余白の設定を回転させるため、この 2 種類の値を変換する必要があります。
PageMargin? pgMar = sectPr.Descendants<PageMargin>().FirstOrDefault();
if (pgMar is not null)
{
// Rotate margins. Printer settings control how far you
// rotate when switching to landscape mode. Not having those
// settings, this code rotates 90 degrees. You could easily
// modify this behavior, or make it a parameter for the
// procedure.
if (pgMar.Top is null || pgMar.Bottom is null || pgMar.Left is null || pgMar.Right is null)
{
throw new ArgumentNullException("One or more of the PageMargin elements is null.");
}
var top = pgMar.Top.Value;
var bottom = pgMar.Bottom.Value;
var left = pgMar.Left.Value;
var right = pgMar.Right.Value;
pgMar.Top = new Int32Value((int)left);
pgMar.Bottom = new Int32Value((int)right);
pgMar.Left = new UInt32Value((uint)System.Math.Max(0, bottom));
pgMar.Right = new UInt32Value((uint)System.Math.Max(0, top));
}
サンプル コード
C# と Visual Basic の完全な SetPrintOrientation
コード サンプルを次に示します。
static void SetPrintOrientation(string fileName, string orientation)
{
PageOrientationValues newOrientation = orientation.ToLower() switch
{
"landscape" => PageOrientationValues.Landscape,
"portrait" => PageOrientationValues.Portrait,
_ => throw new System.ArgumentException("Invalid argument: " + orientation)
};
using (var document = WordprocessingDocument.Open(fileName, true))
{
if (document?.MainDocumentPart?.Document.Body is null)
{
throw new ArgumentNullException("MainDocumentPart and/or Body is null.");
}
Body docBody = document.MainDocumentPart.Document.Body;
IEnumerable<SectionProperties> sections = docBody.ChildElements.OfType<SectionProperties>();
if (sections.Count() == 0)
{
docBody.AddChild(new SectionProperties());
sections = docBody.ChildElements.OfType<SectionProperties>();
}
foreach (SectionProperties sectPr in sections)
{
bool pageOrientationChanged = false;
PageSize pgSz = sectPr.ChildElements.OfType<PageSize>().FirstOrDefault() ?? sectPr.AppendChild(new PageSize() { Width = 12240, Height = 15840 });
// No Orient property? Create it now. Otherwise, just
// set its value. Assume that the default orientation is Portrait.
if (pgSz.Orient is null)
{
// Need to create the attribute. You do not need to
// create the Orient property if the property does not
// already exist, and you are setting it to Portrait.
// That is the default value.
if (newOrientation != PageOrientationValues.Portrait)
{
pageOrientationChanged = true;
pgSz.Orient = new EnumValue<PageOrientationValues>(newOrientation);
}
}
else
{
// The Orient property exists, but its value
// is different than the new value.
if (pgSz.Orient.Value != newOrientation)
{
pgSz.Orient.Value = newOrientation;
pageOrientationChanged = true;
}
if (pageOrientationChanged)
{
// Changing the orientation is not enough. You must also
// change the page size.
var width = pgSz.Width;
var height = pgSz.Height;
pgSz.Width = height;
pgSz.Height = width;
PageMargin? pgMar = sectPr.Descendants<PageMargin>().FirstOrDefault();
if (pgMar is not null)
{
// Rotate margins. Printer settings control how far you
// rotate when switching to landscape mode. Not having those
// settings, this code rotates 90 degrees. You could easily
// modify this behavior, or make it a parameter for the
// procedure.
if (pgMar.Top is null || pgMar.Bottom is null || pgMar.Left is null || pgMar.Right is null)
{
throw new ArgumentNullException("One or more of the PageMargin elements is null.");
}
var top = pgMar.Top.Value;
var bottom = pgMar.Bottom.Value;
var left = pgMar.Left.Value;
var right = pgMar.Right.Value;
pgMar.Top = new Int32Value((int)left);
pgMar.Bottom = new Int32Value((int)right);
pgMar.Left = new UInt32Value((uint)System.Math.Max(0, bottom));
pgMar.Right = new UInt32Value((uint)System.Math.Max(0, top));
}
}
}
}
}
}