Compartilhar via


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

Este tópico mostra como utilizar as classes no SDK Open XML para o Office para definir programaticamente a orientação de impressão de um documento do Microsoft Word. Contém um método de exemplo SetPrintOrientation para ilustrar esta tarefa.


SetPrintOrientation Method

Pode utilizar o SetPrintOrientation método 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 a modificar (cadeia) e a nova orientação de impressão (PageOrientationValues).

O código seguinte mostra o SetPrintOrientation método .

static void SetPrintOrientation(string fileName, string orientation)

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


Chamar o Método SetPrintOrientation de Exemplo

Para chamar o método de exemplo SetPrintOrientation , transmita uma cadeia que contenha o nome do ficheiro a converter e a cadeia "horizontal" ou "vertical", consoante a orientação pretendida. O código seguinte mostra uma chamada de método de exemplo.

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

Como Funciona o Código

Primeiro, o código seguinte determina a orientação a aplicar e, em seguida, abre o documento com o Open método e define o isEditable parâmetro como para true indicar que o documento deve ser de leitura/escrita. O código obtém uma referência à parte do documento main e, em seguida, utiliza essa referência para obter uma coleção de todos os descendentes do tipo SectionProperties no conteúdo do documento. O código posterior utilizará esta coleção para definir a orientação de cada secção.

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

Iterar Através de Todas as Secções

O bloco seguinte de código itera todas as secções na coleção de SectionProperties elementos. Para cada secção, o código inicializa uma variável que controla se a orientação da página da secçã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 ao obter uma referência para o primeiro PageSize descendente do SectionProperties elemento. Se a referência não for nula, o código atualiza a orientação conforme necessário.

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

    PageSize pgSz = sectPr.ChildElements.OfType<PageSize>().FirstOrDefault() ?? sectPr.AppendChild(new PageSize() { Width = 12240, Height = 15840 });

Definir a Orientação para a Secção

O bloco de código seguinte verifica primeiro se a Orient propriedade do PageSize elemento existe. Tal como acontece com muitas propriedades de elementos Open XML, a propriedade ou atributo poderá ainda não existir. Nesse caso, a obtenção da propriedade devolve uma referência nula. Por predefinição, se a propriedade não existir e a nova orientação for Vertical, o código não atualizará a página. Se a Orient propriedade já existir e o respetivo valor for diferente do novo valor de orientação fornecido como um parâmetro para o método, o código define a Value propriedade da Orient propriedade e define o pageOrientationChanged sinalizador. (O código utiliza o pageOrientationChanged sinalizador para determinar se tem de atualizar o tamanho e as margens da página.)

Observação

Se o código tiver de criar a Orient propriedade, também tem de criar o valor a armazenar na propriedade, como uma nova EnumValue<T> instância, fornecendo a nova orientação no EnumValue construtor.

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

Atualizar o Tamanho da Página

Neste ponto do código, a orientação da página pode ter sido alterada. Se for o caso, o código tem de concluir mais duas tarefas. Tem de atualizar o tamanho da página e atualizar as margens da página da secção. A primeira tarefa é fácil: o seguinte código apenas troca a altura e a largura da página, armazenando os valores no PageSize elemento.

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;

Atualizar as Margens

O passo seguinte no procedimento de exemplo processa as margens da secção. Se a orientação da página tiver sido alterada, o código tem de rodar as margens para corresponderem. Para tal, o código obtém uma referência ao PageMargin elemento da secção. Se o elemento existir, o código roda as margens. Tenha em atenção que o código roda as margens em 90 graus— algumas impressoras rodam as margens em 270 graus e pode modificar o código para ter isso em conta. Tenha também em atenção que as Top propriedades e Bottom do PageMargin objeto são valores assinados e que as Left propriedades e Right são valores não assinados. O código tem de ser convertido entre os dois tipos de valores à medida que roda as definições de margem, conforme mostrado no código seguinte.

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ódigo de exemplo

Segue-se o exemplo de código completo SetPrintOrientation em C# e 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));
                    }
                }
            }
        }
    }
}

Confira também