Изменить ориентацию печати документа обработки текста
В этом разделе показано, как использовать классы в пакете SDK Open XML для Office для программной настройки ориентации печати документа Microsoft Word. Он содержит пример SetPrintOrientation
метода для иллюстрации этой задачи.
Метод SetPrintOrientation
Метод можно использовать для SetPrintOrientation
изменения ориентации печати текстового документа. Метод принимает два параметра, указывающие имя документа для изменения (строка) и новую ориентацию печати (PageOrientationValues).
В следующем коде SetPrintOrientation
показан метод .
static void SetPrintOrientation(string fileName, string orientation)
Для каждого раздела в документе если новые ориентация отличается от раздела текущего ориентацию, код изменяет ориентацию страницы для того раздела. Кроме того код необходимо вручную обновить ширину, высоту и поля для каждого раздела.
Вызов метода SetPrintOrientation образца
Чтобы вызвать пример SetPrintOrientation
метода, передайте строку, содержащую имя файла для преобразования и строку "альбомная" или "книжная" в зависимости от нужной ориентации. В следующем коде показано пример вызова метода.
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
элемента. Если ссылка не имеет значение null, код обновляет ориентация при необходимости.
foreach (SectionProperties sectPr in sections)
{
bool pageOrientationChanged = false;
PageSize pgSz = sectPr.ChildElements.OfType<PageSize>().FirstOrDefault() ?? sectPr.AppendChild(new PageSize() { Width = 12240, Height = 15840 });
Настройка ориентации для раздела
Следующий блок кода сначала проверяет, Orient существует ли свойство PageSize
элемента. Как и в многих свойств элементов Open XML, свойства или атрибута может еще не существует. В этом случае получение свойства возвращает ссылку на значение null. По умолчанию если свойство не существует, и новая ориентация портретный, код не обновить страницу.
Orient
Если свойство уже существует и его значение отличается от нового значения ориентации, указанного в качестве параметра метода, код задает Value
свойство Orient
свойства и задает 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;
}
Обновление размера страницы
На данный момент в коде, ориентацию страницы могут измениться. Если это так, код должен выполнить две дополнительные задачи. Он должен обновление размер страницы и обновление поля страницы для раздела. Первая задача проста: следующий код просто меняет высоту и ширину страницы, сохраняя значения в элементе 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 свойства PageMargin
и Bottom объекта являются значениями подписи, а Left свойства и Right являются неподписанными значениями. Код должен преобразовать между двумя типами значения как поворот параметры полей, как показано в следующем коде.
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));
}
Пример кода
Ниже приведен полный SetPrintOrientation
пример кода на C# и Visual Basic.
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));
}
}
}
}
}
}