Open XML SDK в C#. Класс Paragraph — работа с абзацами

Класс Paragraph — это класс определяющий абзац в документе Word. Содержимое абзаца в документе может состоять из любого сочетания следующих четырёх типов содержимого: свойства абзаца, аннотации (закладки, комментарии, правки), пользовательская разметка, содержимое уровня выполнения (поля, гиперссылки, выполнения). В этой части мы рассмотрим основные свойства и методы класса Paragraph.

Класс Paragraph

Класс Paragraph сериализуется в XML как узел <w:p>. Рассмотрим следующий пример:

using (WordprocessingDocument doc = WordprocessingDocument.Create("hello.docx", DocumentFormat.OpenXml.WordprocessingDocumentType.Document))
{
    MainDocumentPart mainPart = doc.AddMainDocumentPart();
    mainPart.Document = new Document();
    Body body = mainPart.Document.AppendChild(new Body());
    Paragraph para = body.AppendChild(new Paragraph(new Run(new Text("Hello World"))));

    para.ParagraphProperties = new ParagraphProperties
    {
        Justification = new Justification() 
        {
            Val = JustificationValues.Center
        }
    };

    for (int i = 0; i < 3; i++)
    {
        Run run = new Run(new Run(new Text($"Строка {i + 1}")));
        para.AppendChild(run);
    }
}

Здесь мы создаем новый документ Word в который добавляем один параграф, добавляя в него сразу одну строку текста:

Paragraph para = body.AppendChild(new Paragraph(new Run(new Text("Hello World"))));

у этого параграфа мы устанавливаем свойство — выравнивание текста по горизонтали:

para.ParagraphProperties = new ParagraphProperties
{
    Justification = new Justification() 
    {
        Val = JustificationValues.Center
    }
};

После этого, мы запускаем цикл и добавляем в документ ещё три строки текста. При этом, мы не создаем новые параграфы — текст добавляется в уже существующий. В результате, мы получим документ со следующей разметкой XML:

<?xml version="1.0" encoding="utf-8"?>
<w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
    <w:body>
        <w:p>
            <w:pPr>
                <w:jc w:val="center" />
            </w:pPr>
            <w:r>
                <w:t>Hello World</w:t>
            </w:r>
            <w:r>
                <w:r>
                    <w:t>Строка 1</w:t>
                </w:r>
            </w:r>
            <w:r>
                <w:r>
                    <w:t>Строка 2</w:t>
                </w:r>
            </w:r>
            <w:r>
                <w:r>
                    <w:t>Строка 3</w:t>
                </w:r>
            </w:r>
        </w:p>
    </w:body>
</w:document>

В приложении MS Word этот документ будет выглядеть следующим образом:

Класс ParagraphРассмотрим более подробно свойства класса Paragraph, которые мы можем использовать при работе с документом.

Свойства класса Paragraph

Класс Paragraph предоставляет нам следующие свойства для работы с абзацами в документе Word:

Свойство Тип Описание
NoSpellError OnOffValue Это свойство доступно только в Office 2010 и более поздних версиях. Указывает, свободен ли текст абзаца от обнаруженных ошибок правописания.

Значения атрибута:
  • true (1) — означает, что ошибки правописания в абзаце не обнаружены.
  • true (0) — указывает, что информация об ошибках правописания в тексте абзаца недоступна.
ParagraphId HexBinaryValue Идентификатор абзаца в документе
ParagraphProperties ParagraphProperties Свойства абзаца (выравнивание по горизонтали и вертикали, перенос слов и т.д.)
TextId HexBinaryValue Идентификатор текста в абзаце

Также у класса определен ряд свойств с префиксом Rsid, относящиеся к работе с ревизиями документа. Эти свойства мы пока рассматривать не будем. Наиболее полезным для нас свойством класса Paragraph является свойство ParagraphProperties представленное объектом одноименного класса. В классе ParagraphProperties также содержится ряд свойств-объектов каждое из которых отвечает за определенную настройку абзаца. С одним из таких свойств мы познакомились в примере выше. Рассмотрим какие ещё свойства мы можем использовать для настройки абзацев в документе Word.

Настройка свойств абзаца в документе Word. Класс ParagraphProperties

Объекты этого класса сериализуются как <w:pPr>и определяют набор свойств абзаца, которые применяются к содержимому родительского абзаца после того, как к тексту применены все другие свойства стиля, нумерации или таблицы. Эти свойства определяются как прямое форматирование, поскольку они применяются непосредственно к абзацу и заменяют любое форматирование, заданное стилями.

Класс ParagraphProperties предоставляет нам следующие свойства:

Свойство Тип Описание
AdjustRightIndent AdjustRightIndent? Автоматическая настройка правого отступа при использовании сетки документа
AutoSpaceDE AutoSpaceDE? Автоматическая настройка интервалов в текстах на латинице и восточноазиатских языках
AutoSpaceDN AutoSpaceDN? Автоматическая настройка интервалов для восточноазиатского текста и цифр
ConditionalFormatStyle ConditionalFormatStyle? Условное форматирование абзацев. Используется если абзац расположен внутри ячейки таблицы
ContextualSpacing ContextualSpacing? Указывает, что любой интервал, указанный до или после этого абзаца с помощью элемента spacing, не должен применяться, если предыдущий и следующий абзацы оформлены в одном стиле. Это значение обычно используется для абзацев в списках, где нежелателен любой интервал между последующими элементами списка, даже если он унаследован от другого стиля
Indentation Indentation? Определяет набор свойств отступа, применяемых к текущему абзацу.
Justification Justification? Определяет выравнивание абзаца, которое будет применяться к тексту в этом абзаце.
KeepLines KeepLines? Указывает, что при отображении документа в режиме просмотра страницы все строки этого абзаца по возможности должны располагаться на одной странице.
KeepNext KeepNext? Указывает, что при отображении документа в постраничном режиме содержимое этого абзаца по возможности частично отображается на той же странице, что и следующий абзац
MirrorIndents MirrorIndents? Указывает, следует ли интерпретировать отступы абзацев как зеркальные. Если этот элемент присутствует, начальный отступ становится внутренним отступом (ближайшим к корешку), а конечный отступ — внешним отступом (наиболее удалённым от корешка)
NumberingProperties NumberingProperties? Ссылка на определение нумерации. Например, это свойство может использоваться, когда текущий абзац должен нумероваться с продолжением нумерации предыдущего нумерованного списка
OverflowPunctuation OverflowPunctuation? Указывает, что текст в данном абзаце может выходить за пределы, установленные отступами или полями, на один символ, если этот символ является знаком препинания
PageBreakBefore PageBreakBefore? Указывает на то, что при отображении документа в постраничном режиме содержимое этого абзаца отображается в начале новой страницы документа
ParagraphBorders ParagraphBorders? Определяет границы родительского абзаца. Каждый дочерний элемент должен указывать конкретный тип границы (слева, справа, снизу, сверху и между)
Shading Shading? Определяет выделение (заливку) абзаца
SpacingBetweenLines SpacingBetweenLines? Определяет межстрочный и межбуквенный интервал, который будет применяться к содержимому этого абзаца при его отображении
TextAlignment TextAlignment? Определяет вертикальное выравнивание всего текста в каждой строке абзаца. Если высота строки (без учёта дополнительных пробелов) больше, чем высота одного или нескольких символов в строке, все символы выравниваются относительно друг друга в соответствии с этим элементом
WordWrap WordWrap? Определяет должен ли пользователь разбивать текст, превышающий размер строки, на две части (разбиение на уровне символов) или переносить слово на следующую строку (разбиение на уровне слов)

Как видите, абзац в документе Word может иметь достаточно много различных настроек. Рассмотрим несколько примеров использования этих настроек при работе с документами Word.

Как в Open XML сделать отступы в абзаце?

Для того, чтобы в Open XML настроить отступы в абзаце, необходимо воспользоваться свойством Indentation у объекта ParagraphProperties . При этом, размерность отступов в Indentation выражается в таких единицах измерения, как «двадцатая часть точки» (dxa). Чтобы разобраться с тем, что это за единица измерения и как с ней работать, рассмотрим следующий пример:

using WordprocessingDocument doc = WordprocessingDocument.Create("hello.docx", DocumentFormat.OpenXml.WordprocessingDocumentType.Document);

MainDocumentPart mainPart = doc.AddMainDocumentPart();
mainPart.Document = new Document();
Body body = mainPart.Document.AppendChild(new Body());
Paragraph para = body.AppendChild(new Paragraph(new Run(new Text("Это строка текста с отступами слева, справа, снизу и сверху"))));


//устанавливаем настройки абзаца
para.ParagraphProperties = new ParagraphProperties
{
    //устанавливаем отступы слева и справа
    Indentation = new Indentation() { Left="1440", Right = "720"}
};

Здесь мы устанавливаем отступы для абзаца слева и справа равными 1440 и 720dxa соответственно. В документе Word эти отступы будут выглядеть следующим образом:

Как посчитались 2,54 и 1,27 см? Давайте разбираться. Вначале переведем dxa в точки:

1440 / 20 = 72 pt.

теперь вспомним, что 1 дюйм — это 2,54 см., то есть ровно то значение, которое мы получили в Word. То есть, условно, можно сказать, что Word обрабатывает документы с разрешением 72 dpi (точек на дюйм).

Теперь мы можем написать метод, который позволит нам устанавливать отступы в абзаце, используя привычные нам сантиметры:

public static int CmToDxa(double value)
{
    //переводим сантиметры в дюймы
    var inches = value / 2.54;
    //переводим дюймы в точки при разрешении 72 dpi
    var dpi = inches * 72;
    //переводим точки в dxa
    var dxa = dpi * 20;
    return (int)Math.Ceiling(dxa);
}

Теперь, используя этот метод, мы можем использовать для работы с отступами сантиметры, например,

para.ParagraphProperties = new ParagraphProperties
{
    //устанавливаем отступы слева и справа
    Indentation = new Indentation() 
    { 
        Left=$"{CmToDxa(1.5)}", 
        Right = $"{CmToDxa(1)}" 
    }
};

Отступы в абзаце будут равны 1,5 см слева и 1 см справа:

Как в Open XML выравнивать текст в абзаце (по левому край, по центру, по правому краю или по ширине)?

Для того, чтобы в Open XML выравнять текст в абзаце, используется свойство Justification объекта ParagraphProperties. Например,

using WordprocessingDocument doc = WordprocessingDocument.Create("hello.docx", DocumentFormat.OpenXml.WordprocessingDocumentType.Document);

MainDocumentPart mainPart = doc.AddMainDocumentPart();
mainPart.Document = new Document();
Body body = mainPart.Document.AppendChild(new Body());
Paragraph para = body.AppendChild(new Paragraph(new Run(new Text("Это строка текста с выравниванием текста по ширине. Это пример работы с Open XML и документов Word"))));


//устанавливаем настройки абзаца
para.ParagraphProperties = new ParagraphProperties
{
    Justification = new Justification()
    {
        Val = JustificationValues.Both
    }

};

Свойство Val объекта Justification представляет собой структуру JustificationValues. Для выравнивания мы можем использовать следующие значения:

  • Both — выравнивание по ширине
  • Center — выравнивание по центру
  • Distribute — распределить текст по ширине
  • End или Right — выравнивание по правому краю
  • Start или Left — выравнивание по левому краю

В представленном выше примере текст выравнивается по ширине, например, так:

Иначе ведет себя значение Distribute. Например, изменим настройки абзаца вот так:

para.ParagraphProperties = new ParagraphProperties
{
    Justification = new Justification()
    {
        Val = JustificationValues.Distribute
    }

};

и посмотрим на результат:

Как видите, текст во второй строке распределился так, чтобы между всеми символами было равное расстояние, а сам текст занимал всю строку.

Как в Open XML сделать заливку абзаца?

Для того, чтобы в Open XML сделать заливку в абзаце, необходимо использовать свойство Shading объекта ParagraphProperties. Чтобы продемонстрировать работу с этим свойством, воспользуемся предыдущим примером и перепишем его следующим образом:

using WordprocessingDocument doc = WordprocessingDocument.Create("hello.docx", DocumentFormat.OpenXml.WordprocessingDocumentType.Document);

MainDocumentPart mainPart = doc.AddMainDocumentPart();
mainPart.Document = new Document();
Body body = mainPart.Document.AppendChild(new Body());
Paragraph para = body.AppendChild(new Paragraph(new Run(new Text("Это строка текста с выравниванием текста по ширине. Это пример работы с Open XML и документов Word"))));


//устанавливаем настройки абзаца
para.ParagraphProperties = new ParagraphProperties
{
    Shading = new Shading() { Color = "57ff57", Val = ShadingPatternValues.DiagonalCross, },

    Justification = new Justification()
    {
        Val = JustificationValues.Distribute
    }

};

Здесь мы используем свойства объекта типа ShadingColor — для установки цвета заливки и Val — способ заливки. В данном случае, цвет устанавливается как шестнадцатеричное значение, а Val указывает на то, что заливка будет крест-на-крест. В документе Word наш абзац будет выглядеть следующим образом:

Также, мы можем воспользоваться цветами темы оформления. Для этого используется перечисление ThemeColorValues. Например, воспользуемся одним из цветов темы оформления для заливки:

para.ParagraphProperties = new ParagraphProperties
{
    Shading = new Shading() {Val = ShadingPatternValues.DiagonalCross, ThemeColor=ThemeColorValues.Accent3},

    Justification = new Justification()
    {
        Val = JustificationValues.Distribute
    }

};

В данном случае, мы воспользовались свойством ThemeColorValues,которое и принимает в качестве значения идентификатор цвета темы оформления. Теперь заливка абзаца будет выглядеть вот так:

Как в Open XML установить интервал между абзацами?

Чтобы в Open XML установить интервал между абзацами, необходимо использовать свойство SpacingBetweenLines объекта ParagraphProperties. В MS Word эта настройка выглядит следующим образом:

Open XML Paragraph - интервал между абзацами

При этом, необходимо учитывать, что расстояние между абзацами рассчитывается как двадцатые доли пункта. Например, если нам необходимо установить интервал между абзацами 4 пт, то настройка свойств параграфа должна быть следующей:

para.ParagraphProperties.SpacingBetweenLines = new SpacingBetweenLines()
{
    After = "80", //интервал после = 80/20 = 4пт
    Before = "80",//интервал до = 80/20 = 4пт
};

Как в Open XML установить межстрочный интервал?

Чтобы в Open XML установить межстрочный интервал, необходимо использовать свойство SpacingBetweenLines объекта ParagraphProperties. В MS Word эта настройка выглядит следующим образом:

Open XML Paragraph - межстрочный интервал

При установлении межстрочного интервала стоит учитывать, что здесь в Open XML используется такое понятие как «обычный межстрочный интервал», который составляет 12пт или, в единицах измерения Open XML — 240. От этого значения может рассчитываться множитель для межстрочного интервала. Например, установим в нашем абзаце междустрочный интервал как «множитель 1,2»:

para.ParagraphProperties.SpacingBetweenLines = new SpacingBetweenLines()
{
    Line = "288", //14,4пт  
    LineRule = LineSpacingRuleValues.Auto, //междустрочный интервал рассчитывается как 288/240 = 1,2
};

Если нам необходимо установить междустрочный интервал, используя такие настройки, как «точно» или «минимум», то необходимо устанавливать другие значения параметра LineRuleExact для точного значения интервала или AtLeast — для минимального значения. Например, установим междустрочный интервал, как точно 14,4пт

para.ParagraphProperties.SpacingBetweenLines = new SpacingBetweenLines()
{
    Line = "288",
    LineRule = LineSpacingRuleValues.Exact,
};

Итого

В этой части мы познакомились в общих чертах с тем, как в Open XML ведется работа с абзацами — рассмотрели свойства класса Paragraph и написали небольшой пример использования настроек абзаца при работе с Open XML в C#. За пределами этой статьи также остался такой вопрос, как использование стилей оформления текста, например, как сделать текст в стиле «Заголовок 1» или «Заголовок 2». К этому вопросу мы обязательно вернемся позднее, когда изучим работу с классами, необходимыми для выполнения таких операций в Open XML.

Подписаться
Уведомить о
guest
0 Комментарий
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии