利用 Open XML 文件格式,可以指定 Microsoft Word 文档的打印方向。Open XML SDK 2.0 添加了可简化对 Open XML 文件格式的访问的强类型类:SDK 将简化处理打印方向这一任务,因为它使您能够更轻松地与 Open XML 内容中的元素进行交互。此直观操作方法附带的代码示例将介绍如何使用 SDK 来实现此目标。
此直观操作方法附带的示例将包含指定 Word 2007 或 Word 2010 文档的打印方向所需的代码。以下各节描述了该代码。
设置引用
若要使用 Open XML SDK 2.0 中的代码,您必须向您的项目添加一些引用。虽然示例项目已包含这些引用,但您必须在您的代码中显式引用以下程序集:
您还应将下面的 using/Imports 语句添加到代码文件的顶部。
Imports DocumentFormat.OpenXml.Wordprocessing
Imports DocumentFormat.OpenXml.Packaging
Imports DocumentFormat.OpenXml
using System.Linq;
using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Wordprocessing;
检查过程
WDSetPrintOrientation 过程接受两个参数:一个指示要修改的文档的名称的参数(字符串)和一个描述新的打印方向的参数 (DocumentFormat.OpenXml.Wordprocessing.PageOrientationValues)。
Public Sub WDSetPrintOrientation(
ByVal fileName As String,
ByVal newOrientation As PageOrientationValues)
public static void WDSetPrintOrientation(
string fileName, PageOrientationValues newOrientation)
对于文档中的每个部分,如果新的方向与当前部分的打印方向不同,则此过程将修改该部分的打印方向。此外,此过程必须更新每个部分的宽度、高度和边距。
若要调用此过程,请传递参数值,如示例代码中所示。在您运行示例代码之前,请确认您提供了一个名为 C:\temp\Orientation.docx 的文档,该文档(用于演示)包含多个部分。
WDSetPrintOrientation(
"C:\temp\Orientation.docx", PageOrientationValues.Portrait)
WDSetPrintOrientation(
@"C:\temp\Orientation.docx", PageOrientationValues.Portrait);
访问文档
该代码首先会使用 WordprocessingDocument.Open 方法打开文档,并指示应打开文档以供读写访问(最后的 true 参数)。代码将保留一个 Boolean 变量,以跟踪文档是否已更改(以便在出现此情况时能够保存文档)。代码将检索对主文档部分的引用,然后使用该引用检索文档内容中的所有 SectionProperties 后代的集合 - 稍后,代码将使用该集合依次为每个部分设置方向。
Using document = WordprocessingDocument.Open(fileName, True)
Dim documentChanged As Boolean = False
Dim docPart = document.MainDocumentPart
Dim sections = docPart.Document.Descendants(
Of SectionProperties)()
' Code removed here…
End Using
using (var document = WordprocessingDocument.Open(fileName, true))
{
bool documentChanged = false;
var docPart = document.MainDocumentPart;
var sections = docPart.Document.Descendants<SectionProperties>();
// Code removed here…
}
循环访问各个部分
下一个代码块将循环访问 SectionProperties 元素集合的所有部分。对于每个部分,该代码都将初始化一个用于跟踪部分的页面方向是否已更改的变量(可以在不进行更改的情况下使新方向与初始方向匹配),因此,该代码可以更新页面大小和边距。然后,该代码将检索对 SectionProperties 元素的第一个 PageSize 后代的引用。如果此引用不为 空 ,则该代码将根据需要固定方向。
For Each sectPr As SectionProperties In sections
Dim pageOrientationChanged As Boolean = False
Dim pgSz As PageSize = sectPr.Descendants(Of PageSize).FirstOrDefault
If pgSz IsNot Nothing Then
' Code removed here…
End If
Next
foreach (SectionProperties sectPr in sections)
{
bool pageOrientationChanged = false;
PageSize pgSz = sectPr.Descendants<PageSize>().FirstOrDefault();
if (pgSz != null)
{
// Code removed here…
}
}
设置部分方向
下一个代码块首先会验证 PageSize 元素的 Orient 属性是否存在。与 Microsoft Word Open XML 元素的许多属性一样,该属性 (Property)/属性 (Attribute) 也可能不存在。在此示例中,使用 Open XML SDK 2.0 检索该属性将返回 null 引用。如果该属性不存在,且新方向为 Portrait,则无需执行任何操作 - 这是默认设置,且无需修改文档。如果 Orient 属性已存在,并且其值与作为参数提供给该方法的新方向值不同,则该代码将设置 Orient 属性的 Value 属性,并将设置 pageOrientationChanged 和 documentChanged 标志。(该代码使用 pageOrientationChanged 标志来确定是否必须更新页面大小和边距。它使用 documentChanged 标志来确定是否必须在最后保存文档)。请注意,如果该代码必须创建 Orient 属性,则它还必须创建要在该属性中作为新的 EnumValue 实例存储的值,并在 EnumValue 构造函数中提供新方向。
If pgSz.Orient Is Nothing Then
If newOrientation <> PageOrientationValues.Portrait Then
pageOrientationChanged = True
documentChanged = True
pgSz.Orient = New EnumValue(
Of PageOrientationValues)(newOrientation)
End If
Else
If pgSz.Orient.Value <> newOrientation Then
pgSz.Orient.Value = newOrientation
pageOrientationChanged = True
documentChanged = True
End If
if (pgSz.Orient == null)
{
if (newOrientation != PageOrientationValues.Portrait)
{
pageOrientationChanged = true;
documentChanged = true;
pgSz.Orient = new EnumValue<PageOrientationValues>(newOrientation);
}
}
else
{
if (pgSz.Orient.Value != newOrientation)
{
pgSz.Orient.Value = newOrientation;
pageOrientationChanged = true;
documentChanged = true;
}
}
固定页面大小
此时,在代码中,页面方向可能已更改。如果出现此情况,则代码必须执行至少两个任务:它必须固定页面大小,并且必须固定部分的页边距。该代码将交换页面高度和宽度,并将值存储到 PageSize 元素中。
If pageOrientationChanged Then
Dim width = pgSz.Width
Dim height = pgSz.Height
pgSz.Width = height
pgSz.Height = width
' Code removed here…
End If
if (pageOrientationChanged)
{
var width = pgSz.Width;
var height = pgSz.Height;
pgSz.Width = height;
pgSz.Height = width;
// Code removed here…
}
固定页边距
本示例过程中的下一个步骤是,处理部分的页边距。如果页面方向已更改,则该代码必须旋转页边距以进行匹配。为此,该代码将检索对部分的 PageMargin 元素的引用,如果该引用存在,则旋转页边距。请注意,该代码会将页边距旋转 90 度 - 而一些打印机会将页边距旋转 270 度,并且您可以修改代码来说明这一点。另请注意,PageMargin 对象的 Top 和 Bottom 属性为有符号值,而 Left 和 Right 属性为无符号值。当该代码旋转页边距设置时,它必须在这两类值之间转换。
Dim pgMar As PageMargin =
sectPr.Descendants(Of PageMargin).FirstOrDefault()
If pgMar IsNot Nothing Then
' 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.
Dim top = pgMar.Top.Value
Dim bottom = pgMar.Bottom.Value
Dim left = pgMar.Left.Value
Dim right = pgMar.Right.Value
pgMar.Top = CType(left, Int32Value)
pgMar.Bottom = CType(right, Int32Value)
pgMar.Left = CType(System.Math.Max(
0, CType(bottom, Int32Value)), UInt32Value)
pgMar.Right = CType(System.Math.Max(
0, CType(top, Int32Value)), UInt32Value)
End If
PageMargin pgMar = sectPr.Descendants<PageMargin>().FirstOrDefault();
if (pgMar != 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.
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));
}
保存文档
完成修改后,该代码将确定文档是否已更改;如果文档已更改,则该代码将保存文档。
If documentChanged Then
docPart.Document.Save()
End If
if (documentChanged)
{
docPart.Document.Save();
}
示例过程
下面的代码示例包含完整的示例过程。
Public Sub WDSetPrintOrientation(
ByVal fileName As String, ByVal newOrientation As PageOrientationValues)
Using document = WordprocessingDocument.Open(fileName, True)
Dim documentChanged As Boolean = False
Dim docPart = document.MainDocumentPart
Dim sections = docPart.Document.Descendants(Of SectionProperties)()
For Each sectPr As SectionProperties In sections
Dim pageOrientationChanged As Boolean = False
Dim pgSz As PageSize = sectPr.Descendants(Of PageSize).FirstOrDefault
If pgSz IsNot Nothing Then
' No Orient property? Create it now. Otherwise, just set its value.
' Assume that the default orientation is Portrait.
If pgSz.Orient Is Nothing Then
' Need to create the attribute. You do not need to
' create the Orient property if the property doesn't already
' exist and you are setting it to Portrait. That's the default value.
If newOrientation <> PageOrientationValues.Portrait Then
pageOrientationChanged = True
documentChanged = True
pgSz.Orient = New EnumValue(Of PageOrientationValues)(newOrientation)
End If
Else
' The Orient property exists, but its value
' is different than the new value.
If pgSz.Orient.Value <> newOrientation Then
pgSz.Orient.Value = newOrientation
pageOrientationChanged = True
documentChanged = True
End If
End If
If pageOrientationChanged Then
' Changing the orientation isn't enough. You must also change the page size.
Dim width = pgSz.Width
Dim height = pgSz.Height
pgSz.Width = height
pgSz.Height = width
Dim pgMar As PageMargin =
sectPr.Descendants(Of PageMargin).FirstOrDefault()
If pgMar IsNot Nothing Then
' 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.
Dim top = pgMar.Top.Value
Dim bottom = pgMar.Bottom.Value
Dim left = pgMar.Left.Value
Dim right = pgMar.Right.Value
pgMar.Top = CType(left, Int32Value)
pgMar.Bottom = CType(right, Int32Value)
pgMar.Left = CType(System.Math.Max(
0, CType(bottom, Int32Value)), UInt32Value)
pgMar.Right = CType(System.Math.Max(
0, CType(top, Int32Value)), UInt32Value)
End If
End If
End If
Next
If documentChanged Then
docPart.Document.Save()
End If
End Using
End Sub
public static void WDSetPrintOrientation(
string fileName, PageOrientationValues newOrientation)
{
using (var document = WordprocessingDocument.Open(fileName, true))
{
bool documentChanged = false;
var docPart = document.MainDocumentPart;
var sections = docPart.Document.Descendants<SectionProperties>();
foreach (SectionProperties sectPr in sections)
{
bool pageOrientationChanged = false;
PageSize pgSz = sectPr.Descendants<PageSize>().FirstOrDefault();
if (pgSz != null)
{
if (pgSz.Orient == null)
{
if (newOrientation != PageOrientationValues.Portrait)
{
pageOrientationChanged = true;
documentChanged = 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;
documentChanged = true;
}
}
if (pageOrientationChanged)
{
var width = pgSz.Width;
var height = pgSz.Height;
pgSz.Width = height;
pgSz.Height = width;
PageMargin pgMar =
sectPr.Descendants<PageMargin>().FirstOrDefault();
if (pgMar != 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));
}
}
}
}
if (documentChanged)
{
docPart.Document.Save();
}
}
}
此直观操作方法附带的示例描述了将设置 Word 文档的打印方向的代码。若要使用该示例,必须安装 Open XML SDK 2.0(可通过"浏览"一节中列出的链接获得)。该示例还将使用作为 Open XML SDK 2.0 代码示例集的一部分包含的修改后的代码。"浏览"一节还包括指向完整代码示例集的链接,但您无需下载并安装代码示例即可使用该示例。
示例应用程序仅演示了由 Open XML SDK 2.0 提供的一些可用来修改文档结构的可用属性和方法。有关详细信息,请参阅 Open XML SDK 2.0 Productivity Tool 附带的文档。单击应用程序窗口左下角的"Open XML SDK 文档"选项卡,并搜索要研究的类。尽管该文档当前不包含代码示例,但借助此处所示的示例和文档,您应能成功修改示例应用程序。 |