Время прочтения: 6 мин.

Можно создать шаблон документа в Word, используя элементы управления содержимым (Content Control), и ограничить редактирование в нем. Но в документах бывает такое содержимое, которое необходимо добавлять или удалять. Например, добавить еще одну строку в таблицу, добавить пункт распоряжения и т.п. В таком случае будет удобнее создать собственную вкладку в Word, которая позволит изменять структуру документа при необходимости. В этой статье будет показано, как создавать Надстройку VSTO для документа Word.

Давайте рассмотрим небольшой пример программы, которая будет формировать шаблон документа. Документ выглядит следующим образом:

В Visual Studio создадим новый проект «ExampleRibbonWord» типа «Надстройка VSTO для Word 2013 и Word 2016»:

Нам необходимо создать ленту, на которой будут размещаться кнопки и выпадающие списки. Для этого щелкаем правой кнопкой мыши на названии проекта и добавляем элемент Лента (визуальный конструктор):

Вот такая лента у нас создалась:

Теперь в окне свойств элементов управления изменим названия нашей вкладки (Tab1) и группы (Group1).

tab1.Label=”Мои шаблоны”

group1.Label=”Создание шаблона”

Для начала давайте добавим на ленту кнопку (Button1), при нажатии на которую в документе Word будет создаваться шаблон. Свойства Label задаем= «Пример шаблона».

Теперь создадим событие Click для кнопки. Кнопка должна в документе Word сформировать указанный выше шаблон. В элементах управления содержимым мы разместим следующую информацию: дата распоряжения, номер распоряжения, название распоряжения, текст распоряжения, должность и ФИО. Пункты распоряжения мы разместим в таблице без границ. Каждый пункт распоряжения будет также размещаться в элементе управления. При нажатии на кнопку таблица должна сформироваться с одной строкой и двумя столбцами (номер пункта, текст пункта). В дальнейшем необходимо будет реализовать функционал, который позволит добавлять новые пункты в распоряжение.

Код:

public partial class Ribbon1
    {
        private void Ribbon1_Load(object sender, RibbonUIEventArgs e)
        {

        }

        //Создание текстового элемента управления
        //диапазон, тэг (по нему в дальнейшем можно получать содержимое), замещающий текст, когда элемент не заполнен, название 
        private void AddContentControlText(Word.Range r, string tagRTC, string PlaceholderTextRTC, string titleRTC)
        {
            Word.Document currentDocument = Globals.ThisAddIn.Application.ActiveDocument;
            Document extendedDocument = Globals.Factory.GetVstoObject(currentDocument);
            RichTextContentControl rTC = extendedDocument.Controls.AddRichTextContentControl(r, tagRTC);
            rTC.PlaceholderText = PlaceholderTextRTC;
            rTC.Tag = tagRTC;
            rTC.LockContentControl = true;//элемент нельзя удалить
            rTC.Title = titleRTC;
        }

        //Создание элемента управления даты 
        //диапазон, тэг (по нему в дальнейшем можно получать содержимое), замещающий текст, когда элемент не заполнен, стиль даты, название 
        private void AddContentControlDate(Word.Range r, string tagDPC, string PlaceholderTextDPC, string styleDate, string titleDPC)
        {
            Word.Document currentDocument = Globals.ThisAddIn.Application.ActiveDocument;
            Document extendedDocument = Globals.Factory.GetVstoObject(currentDocument);
            DatePickerContentControl dPC = extendedDocument.Controls.AddDatePickerContentControl(r, tagDPC);
            dPC.PlaceholderText = PlaceholderTextDPC;
            dPC.Tag = tagDPC;
            dPC.LockContentControl = true;//элемент нельзя удалить
            dPC.DateDisplayFormat = styleDate;
            dPC.Title = titleDPC;
        }

        //создаем собственный стиль
        private void CreateMyStyle(Word.Document doc)
        {
            Word.Style style = doc.Styles.Add("MyStyleParagraph", Word.WdStyleType.wdStyleTypeParagraph);
            style.Font.Size = 12;
            style.Font.Name = "Times New Roman";
        }

        private void button1_Click(object sender, RibbonControlEventArgs e)
        {
            //при нажатии на кнопку появится диалоговое окно, которое спросит где создать шаблон в текущем открытом word или в новом.
            //при этом, если текущий документ будет не пустым, то шаблон создастся в новом документе
            Word.Document doc;
            DialogResult dialogResult = MessageBox.Show("Создать шаблон в новом документе?", "Создание шаблона", MessageBoxButtons.YesNo);
            if (dialogResult == DialogResult.Yes) doc = new Word.Document();
            else
            {
                doc = Globals.ThisAddIn.Application.ActiveDocument;
                if (doc.Characters.Count > 1)
                {
                    MessageBox.Show("Текущий документ не пустой! Шаблон будет создан в новом документе!");
                    doc = new Word.Document();
                }
            }

            //создаем стиль в текущем документе
            CreateMyStyle(doc);

            //создаем абзац
            doc.Paragraphs.Add();
            Word.Paragraph p = doc.Paragraphs.First;
            Word.Range r = p.Range;
            r.Font.Bold = 1;// шрифт жирный
            r.Text = "РАСПОРЯЖЕНИЕ";//текст абзаца
            r.ParagraphFormat.set_Style(doc.Styles["MyStyleParagraph"]); //стиль применяем

            //создаем абзац и вставляем в него 2 элемента управления
            //для каждого типа элемента управления создаем функцию с параметрами
            doc.Paragraphs.Add();
            p = doc.Paragraphs.Last;
            r = p.Range;
            r.ParagraphFormat.set_Style(doc.Styles["MyStyleParagraph"]);
            //дата распоряжения
            AddContentControlDate(r, "DateRaspr", "Дата распоряжения", "d MMMM yyyy г.", "Дата распоряжения");
            r = doc.Range(p.Range.End - 1, p.Range.End - 1);
            r.Text = " № ";
            //номер распоряжения
            AddContentControlText(r, "NumberRaspr", "Номер распоряжения", "Номер распоряжения");

            doc.Paragraphs.Add();
            p = doc.Paragraphs.Last;
            p.SpaceAfter = 18;
            r = p.Range;
            r.ParagraphFormat.set_Style(doc.Styles["MyStyleParagraph"]);
            r.Font.Bold = 1;
            p.Alignment = Word.WdParagraphAlignment.wdAlignParagraphCenter;//по центру размещаем
            //название распоряжения
            AddContentControlText(r, "NameRaspr", "Название распоряжения", "Название распоряжения");

            doc.Paragraphs.Add();
            p = doc.Paragraphs.Last;
            p.SpaceAfter = 18;
            r = p.Range;
            r.ParagraphFormat.set_Style(doc.Styles["MyStyleParagraph"]);
            p.Alignment = Word.WdParagraphAlignment.wdAlignParagraphCenter;
            //текст распоряжения
            AddContentControlText(r, "TextRaspr", "Текст распоряжения", "Текст распоряжения");

            doc.Paragraphs.Add();
            p = doc.Paragraphs.Last;
            r = p.Range;
            r.ParagraphFormat.set_Style(doc.Styles["MyStyleParagraph"]);
            //таблица для пунктов распоряжения
            Word.Table tbl = doc.Tables.Add(r, 1, 2);
            tbl.Columns[1].SetWidth(doc.Application.CentimetersToPoints(1), Word.WdRulerStyle.wdAdjustFirstColumn);
            tbl.Cell(1, 1).Range.Text = "1.";
            r = doc.Range(tbl.Cell(1, 2).Range.End - 1, tbl.Cell(1, 2).Range.End - 1);
            AddContentControlText(r, "TextPunkt", "Пункт распоряжения", "Пункт распоряжения");

            doc.Paragraphs.Add();
            p = doc.Paragraphs.Last;
            r = p.Range;
            //должность
            AddContentControlText(r, "Dolgnost", "Должность", "Должность");
            r = doc.Range(p.Range.End - 1, p.Range.End - 1);
            r.Paragraphs.TabStops.Add(350, Word.WdAlignmentTabAlignment.wdLeft);
            r.Text = "\t";
            r = doc.Range(p.Range.End - 1, p.Range.End - 1);
            //ФИО
            AddContentControlText(r, "FIO", "ФИО", "ФИО");
        }
    }

Запускаем и получаем вот такой шаблон документа:

Для примера заполним дату распоряжения:

Дата заполнена:

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