Compartilhar via


Alterar a orientação de impressão de um documento de processamento de texto

Este tópico mostra como usar as classes no SDK Open XML para Office para definir programaticamente a orientação de impressão de um documento Microsoft Word 2010 ou Microsoft Word 2013. Ele contém um método SetPrintOrientation de exemplo para ilustrar essa tarefa.


Método SetPrintOrientation

Você pode usar o método SetPrintOrientation para alterar a orientação de impressão de um documento de processamento de palavras. O método aceita dois parâmetros que indicam o nome do documento para modificar (cadeia de caracteres) e a nova orientação de impressão (PageOrientationValues).

O código a seguir mostra o método SetPrintOrientation .

    public static void SetPrintOrientation(
      string fileName, PageOrientationValues newOrientation)

Para cada seção no documento, se a nova orientação for diferente da orientação de impressão atual da seção, o código modificará a orientação de impressão da seção. Além disso, o código deve atualizar manualmente a largura, a altura e as margens para cada seção.


Chamando o método SetPrintOrientation de exemplo

Para chamar o método SetPrintOrientation de exemplo, passe uma cadeia de caracteres que contém o nome do arquivo a ser convertido. O código a seguir mostra uma chamada de método de exemplo.

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

Como o código funciona

O código a seguir primeiro abre o documento usando o método Open e define o parâmetro isEditablecomo true para indicar que o documento deve ser leitura/gravação. O código mantém uma variável booliana que rastreia se o documento foi alterado (para que ele possa salvar o documento posteriormente, se o documento tiver sido alterado). O código recupera uma referência à parte do documento main e usa essa referência para recuperar uma coleção de todos os descendentes do tipo SectionProperties no conteúdo do documento. O código posterior usará essa coleção para definir a orientação para cada seção por sua vez.

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

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

Iterando por todas as seções

O próximo bloco de código itera em todas as seções da coleção de elementos SectionProperties . Para cada seção, o código inicializa uma variável que rastreia se a orientação da página para a seção foi alterada para que o código possa atualizar o tamanho e as margens da página. (Se a nova orientação corresponder à orientação original, o código não atualizará a página.) O código continua recuperando uma referência ao primeiro descendente pageSize do elemento SectionProperties . Se a referência não for nula, o código atualizará a orientação conforme necessário.

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

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

Definindo a Orientação para a Seção

O próximo bloco de código verifica primeiro se a propriedade Orient do elemento PageSize existe. Como acontece com muitas propriedades de elementos Open XML, a propriedade ou atributo pode não existir ainda. Nesse caso, recuperar a propriedade retorna uma referência nula. Por padrão, se a propriedade não existir e a nova orientação for Retrato, o código não atualizará a página. Se a propriedade Orient já existir, e seu valor for diferente do novo valor de orientação fornecido como um parâmetro para o método, o código definirá a propriedade Value da propriedade Orient e definirá a pageOrientationChanged e os sinalizadores documentChanged . (O código usa o sinalizador pageOrientationChanged para determinar se ele deve atualizar o tamanho e as margens da página. Ele usa o sinalizador documentChanged para determinar se ele deve salvar o documento no final.)

Observação

Se o código precisar criar a propriedade Orient , ele também deverá criar o valor a ser armazenado na propriedade, como uma nova instância EnumValue<T> , fornecendo a nova orientação no construtor 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;
        }
    }

Atualizando o tamanho da página

Neste ponto do código, a orientação da página pode ter sido alterada. Nesse caso, o código deve concluir mais duas tarefas. Ele deve atualizar o tamanho da página e atualizar as margens da página para a seção. A primeira tarefa é fácil: o código a seguir apenas troca a altura e a largura da página, armazenando os valores no 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...
    }

Atualizando as margens

A próxima etapa do procedimento de exemplo manipula as margens da seção. Se a orientação da página tiver sido alterada, o código deverá girar as margens para corresponder. Para fazer isso, o código recupera uma referência ao elemento PageMargin para a seção. Se o elemento existir, o código girará as margens. Observe que o código gira as margens em 90 graus— algumas impressoras giram as margens em 270 graus e você pode modificar o código para levar isso em conta. Também esteja ciente de que as propriedades Superior e Inferior do objeto PageMargin são valores assinados e as propriedades esquerda e direita são valores não assinados. O código deve ser convertido entre os dois tipos de valores à medida que gira as configurações de margem, conforme mostrado no código a seguir.

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

Salvar o Documento

Após todas as modificações, o código determina se o documento foi alterado. Se o documento tiver sido alterado, o código o salvará.

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

Código de exemplo

A seguir está o exemplo completo de código SetPrintOrientation em C# e 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();
        }
    }
}

Confira também