Share via


Cambiar la orientación de impresión de un documento de procesamiento de texto

En este tema se muestra cómo usar las clases del SDK de Open XML para Office para establecer mediante programación la orientación de impresión de un documento Microsoft Word 2010 o Microsoft Word 2013. Se incluye un método de ejemplo SetPrintOrientation para ilustrar la tarea.


Método SetPrintOrientation

Puede usar el método SetPrintOrientation para cambiar la orientación de impresión de un documento de procesamiento de texto. El método acepta dos parámetros que indican el nombre del documento que se va a modificar (cadena) y la nueva orientación de impresión (PageOrientationValues).

El siguiente código muestra el método SetPrintOrientation.

    public static void SetPrintOrientation(
      string fileName, PageOrientationValues newOrientation)

Para cada sección del documento, si la nueva orientación difiere de la orientación de impresión actual de la sección, el código modifica la orientación de impresión de la sección. Además, el código debe actualizar manualmente el ancho, la altura y los márgenes de cada sección.


Llamar al método de ejemplo SetPrintOrientation

Para llamar al método de ejemplo SetPrintOrientation, pase una cadena que contenga el nombre del archivo que se debe convertir. El siguiente código muestra una llamada de método de ejemplo.

    SetPrintOrientation(@"C:\Users\Public\Documents\ChangePrintOrientation.docx", 
        PageOrientationValues.Landscape);

Funcionamiento del código

El siguiente código abre el documento mediante el método Open y configura el parámetro isEditable como true para indicar que el documento debe ser de lectura/escritura. El código mantiene una variable booleana que controla si el documento ha cambiado (para que pueda guardar el documento más adelante si se ha cambiado). El código recupera una referencia al elemento de documento principal y, a continuación, usa esa referencia para recuperar una colección de todos los descendientes de tipo SectionProperties dentro del contenido del documento. Más tarde, el código usará esta colección para configurar la orientación de cada sección por separado.

    using (var document = 
        WordprocessingDocument.Open(fileName, true))
    {
        bool documentChanged = false;

        var docPart = document.MainDocumentPart;
        var sections = docPart.Document.Descendants<SectionProperties>();
        // Code removed here...
    }

Iterar todas las secciones

El siguiente bloque de código itera todas las secciones de la colección de elementos SectionProperties. Para cada sección, el código inicializa una variable que controla si se ha cambiado la orientación de la página de la sección, de tal modo que el código pueda actualizar el tamaño de página y los márgenes. (Si la nueva orientación coincide con la orientación original, el código no actualizará la página). El código continúa recuperando una referencia al primer descendiente PageSize del elemento SectionProperties . Si la referencia no es nula, el código actualiza la orientación según sea necesario.

    foreach (SectionProperties sectPr in sections)
    {
        bool pageOrientationChanged = false;

        PageSize pgSz = sectPr.Descendants<PageSize>().FirstOrDefault();
        if (pgSz != null)
        {
            // Code removed here...
        }
    }

Configurar la orientación de la sección

El siguiente bloque de código comprueba primero si existe la propiedad Orient del elemento PageSize . Al igual que con muchas propiedades de elementos Open XML, es posible que la propiedad o el atributo aún no existan. En ese caso, la recuperación de la propiedad devuelve una referencia nula. De forma predeterminada, si la propiedad no existe y la nueva orientación es Vertical, el código no actualizará la página. Si la propiedad Orient ya existe y su valor difiere del nuevo valor de orientación proporcionado como parámetro al método , el código establece la propiedad Value de la propiedad Orient y establece las marcas pageOrientationChanged y documentChanged . (El código usa la marca pageOrientationChanged para determinar si debe actualizar el tamaño y los márgenes de la página. Usa la marca documentChanged para determinar si debe guardar el documento al final).

Nota:

Si el código debe crear la propiedad Orient , también debe crear el valor para almacenar en la propiedad, como una nueva instancia de EnumValue<T> , proporcionando la nueva orientación en el constructor EnumValue .

    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;
        }
    }

Actualizar el tamaño de página

En este punto del código, puede que haya cambiado la orientación de la página. Si es así, el código debe completar dos tareas más. Debe actualizar el tamaño de página y los márgenes de cada sección. La primera tarea es sencilla: el siguiente código simplemente cambia la altura y el ancho de página, y almacena los valores en el elemento 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;
        // Code removed here...
    }

Actualizar los márgenes

El siguiente paso del procedimiento de ejemplo se encarga de los márgenes de cada sección. Si ha cambiado la orientación de la página, el código debe rotar los márgenes para que coincidan. Para ello, el código recupera una referencia al elemento PageMargin de la sección. Si existe el elemento, el código gira los márgenes. Tenga en cuenta que el código gira los márgenes 90 grados; algunas impresoras giran los márgenes 270 grados, por lo que usted podría modificar el código para tenerlo en cuenta. Tenga en cuenta también que las propiedades Top e Bottom del objeto PageMargin son valores firmados y las propiedades Left y Right son valores sin signo. El código debe convertir los dos tipos de valores a medida que gira la configuración de los márgenes, tal y como se muestra en el siguiente código.

    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));
    }

Guardar el documento

Una vez realizadas todas las modificaciones, el código determina si ha cambiado el documento. En caso afirmativo, el código lo guarda.

    if (documentChanged)
    {
        docPart.Document.Save();
    }

Código de ejemplo

A continuación figura el código de ejemplo SetPrintOrientation completo en C# y Visual Basic.

#nullable enable

using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Wordprocessing;
using System;
using System.Linq;

SetPrintOrientation(args[0], args[1]);

// Given a document name, set the print orientation for 
// all the sections of the document.
static void SetPrintOrientation(string fileName, string no)
{
    PageOrientationValues newOrientation = no.ToLower() switch
    {
        "landscape" => PageOrientationValues.Landscape,
        "portrait" => PageOrientationValues.Portrait,
        _ => throw new System.ArgumentException("Invalid argument: " + no)
    };

    using (var document =
        WordprocessingDocument.Open(fileName, true))
    {
        bool documentChanged = false;

        if (document.MainDocumentPart is null)
        {
            throw new ArgumentNullException("MainDocumentPart and/or Body is null.");
        }

        var docPart = document.MainDocumentPart;


        var sections = docPart.Document.Descendants<SectionProperties>();

        foreach (SectionProperties sectPr in sections)
        {
            bool pageOrientationChanged = false;

            PageSize pgSz = sectPr.Descendants<PageSize>().First();

            // 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;
                    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)
                {
                    // 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()) ?? throw new ArgumentNullException("There are no PageMargin elements in the section.");

                    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));
                    }
                }
            }
        }
        if (documentChanged)
        {
            docPart.Document.Save();
        }
    }
}

Vea también