更改字处理文档的打印方向
本主题演示如何使用 Open XML SDK for Office 中的类以编程方式设置Microsoft Word文档的打印方向。 它包含演示此任务的示例 SetPrintOrientation
方法。
SetPrintOrientation 方法
可以使用 SetPrintOrientation
方法更改字处理文档的打印方向。 方法接受两个参数,这些参数指示要修改 (字符串) 的文档的名称,以及 (PageOrientationValues) 的新打印方向。
以下代码显示了 SetPrintOrientation
方法。
static void SetPrintOrientation(string fileName, string orientation)
对于文档中的每个部分,如果新的方向与该部分当前的打印方向不同,则该代码将修改该部分的打印方向。 此外,该代码必须手动更新每个部分的宽度、高度和边距。
调用示例 SetPrintOrientation 方法
若要调用示例 SetPrintOrientation
方法,请传递包含要转换的文件的名称的字符串以及字符串“landscape”或“portrait”,具体取决于所需的方向。 以下代码显示示例方法调用。
SetPrintOrientation(args[0], args[1]);
代码的工作方式
以下代码首先确定要应用的方向,然后使用 方法打开文档 Open ,并将 参数设置为 isEditable
true
以指示文档应可读/写。 代码检索对 main 文档部件的引用,然后使用该引用检索文档内容中类型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
中的所有节。 对于每个部分,该代码都将初始化一个用于跟踪该部分的页面方向是否已更改的变量,以便代码能够更新页面大小和边距。 (如果新方向与原始方向匹配,则代码不会更新页面。) 代码继续检索对元素第一 PageSize 个后代的 SectionProperties
引用。 如果此引用不为空,则该代码将根据需要更新方向。
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 引用。 默认情况下,如果 属性不存在,并且新方向为 Portrait,则代码不会更新页面。
Orient
如果属性已存在,并且其值不同于作为参数提供给 方法的新方向值,则代码将设置 Value
属性Orient
的 属性,并设置 pageOrientationChanged
标志。 (代码使用 pageOrientationChanged
标志来确定它是否必须更新页面大小和 margins。)
注意
如果代码必须创建 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;
}
更新页面大小
此时,在代码中,页面方向可能已更改。 如果是这样,则代码必须完成另外两个任务。 它必须更新页面大小,并更新分区的页边距。 第一个任务很简单 ,以下代码仅交换页面高度和宽度,并将值存储在 元素中 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 度,并且您可以修改代码来说明这一点。
另请注意, Top 对象的 和 Bottom 属性 PageMargin
是有符号值,和 LeftRight 属性是无符号值。 当该代码旋转边距设置时,它必须在这两类值之间转换,如下面的代码所示。
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));
}
}
}
}
}
}