Работа с Word в С#

К началу раздела

logo.gif

Глава 3. Работа с Com сервером Word

Аннотация: В главе представлены собственные практические наработки автора по выводу информации из приложений, написанных в Visual Studio 2003/2005/2008 на C# в Word. Все коды отлажены и неоднократно использовались. Вопросы, которые остались не затронуты, были до сих пор не востребованы в практической работе автора.

Введение. Решение и выбор способа связывания

Прежде чем приступить к рассмотрению поставленных вопросов, создадим новый простой проект (Рис.1.) с именем AppWordExcel (или любым другим, или используем ). Поместим на панели приложения три контрола Button. Свойства Tag контролов установим, соответственно, в значения 1, 2 и 3. Выберем способ "раннего связывания" для сервера автоматизации Word (см. Параграф 1. этого раздела). При написании кода будем использовать .Net сборки взаимодействия с приложениями Microsoft Office. Напомним, что при использовании импортирования библиотеки типов Com объекта и добавлении ссылки на него в Solutation Explorer (References, вкладка Com), нам сразу становится доступно пространство имен объекта (в данном случае Word). При использовании .Net сборок взаимодействия с приложениями Microsoft Office нам, после добавления ссылки на Microsoft.Office.Interop.Word (References, вкладка .Net), потребуется введение алиаса пространства имен Word:

using Word = Microsoft.Office.Interop.Word;

Введение алиаса позволяет не только сократить количество кода при обращении к объектам, но и дает возможность использовать весь код, который мы напишем ниже, для любого способа связывания.

wordexce0202.gif

Рис.1. Проект решения AppWordExcel

Создадим обработчик нажатия для кнопки 1 и замкнем на него обработчики нажатия всех кнопок. Запишем следующий, общий для всех примеров, приводимых ниже, код:

private void button1_Click(object sender, EventArgs e)
{
 int i = Convert.ToInt32(((Button)(sender)).Tag);
 switch(i)
 {
  case 1:
  break;
  case 2:
  break;
  default:
    Close();
  break;
 }
}

В case 1 будем размещать код, в котором выполняется какое-либо действие по старту Excel и выводу информации, в case 2 - дополнительные действия и действия при закрытии приложения, в default - поместим код выхода из приложения.

Обратите внимание на разный способ получения объектов коллекций в Visual Studio 2003 и 2005/2008. Других отличий в примерах приводимого ниже кода нет!

//В Visual Studio 2003
wordparagraph=(Word.Paragraph)wordparagraphs.Item(1);
worddocument.Item(1).Cell(1, 2).Range;
.....
//В Visual Studio 2005/2008
wordparagraph=(Word.Paragraph)wordparagraphs[1];
worddocument.Tables[1].Cell(1, 2).Range;
.....


В начало

Параграф 1. Запуск и закрытие Word из приложения

Объекты, которыми оперирует сервер Word, столь же многочисленны как и объекты для Excel. Основное внимание в параграфе будет уделено тем объектам, которые непосредственно требуются для обмена информацией приложения и сервера.

Рис.2. демонстрирует иерархию объектов Word. Все объекты доступны и из приложения на C#. Отличие заключается в том, что для приложения-контроллера доступны непосредственно Word.Application (экземпляр Word без открытых документов) и Word.Document, (экземпляр Word с открытым или загруженным документом). Остальные объекты Word являются так называемыми внутренними объектами. Это означает, что они не могут быть созданы сами по себе; так, объект Paragraph не может быть создан без документа (впрочем, параграф или абзац равно не доступен и макросу в Word при отсутствии открытого документа).

wordexce0301.gif

Рис.2. Основные объекты Word.

С точки зрения приложения все объекты Word имеют иерархическую структуру. Объект Application - это СOM сервер и оболочка для других объектов. Он может содержать один или более объектов Document. Объекты Document могут содержать такие объекты как Paragraph, Table, Range, Bookmark, Chapter, Word, Sentence, Sections, Headers, Footers... Более правильнее, объект Application может содержать коллекцию Documents - ссылок на объекты типа Document, а каждый объект типа Document - коллекцию Paragraphs или ссылок на объекты типа Paragraph и т.д.

Основные объекты в иерархии объектов Word, необходимые при разработке приложения показаны на Рис.3. И, в тоже время, рисунок лишь поверхностно отображает иерархию. Так, если объект Word.Document содержит объекты Table, Paragraph, Character, Range, Bookmark, InlineShape, Comment, CommandBar.... (доступные через коллекции соответствующих Tables, Paragraphs, Characters, Range, Bookmarks, InlineShapes, Comments, CommandBars ...), то большинство свойств и методов объектов Word доступны приложению и через специфический объект Selection, представляющий некоторую выделенную область документа и, в зависимости от того, какая область документа выделена, меняются его методы и свойства. Объект Selection всегда существует и доступен (даже если ничего не выделено в документе, то он представляет курсор ввода - insertion point). В тоже время, большинство объектов доступно и объекту Range, в том числе и сам документ. Поэтому, когда необходимо "достучаться" до объекта не прямыми путями, то более подойдет для ориентации Рис.2., иначе достаточно и иерархии Рис.3.

wordexce0302.gif

Рис.3. Иерархия основных объектов Word, необходимых при разработке приложения

Работа с документами, параграфами, символами, закладками и т.д. осуществляется путем использования свойств и методов этих объектов. Объекты при создании решений принято определять глобально для того, чтобы обеспечить доступ к ним из любой функции проекта. Определим глобально основной объект Word.Application.

namespace AppWordExcel
{
 public partial class Form1 : Form 
 {
  private Word.Application wordapp;
  .....

Следующий код теперь позволяет выполнять запуск Word и его закрытие при нажатии соответственно кнопок 1 и 2.

case 1:
 try
 {
  //Создаем объект Word - равносильно запуску Word
  wordapp = new Word.Application();
  //Делаем его видимым
  wordapp.Visible = true;
 }
 catch (Exception ex)
 {
  Text = ex.Message;
 }
 break;
 case 2:
  Object saveChanges = Word.WdSaveOptions.wdPromptToSaveChanges;
  Object originalFormat = Word.WdOriginalFormat.wdWordDocument;
  Object routeDocument = Type.Missing;
  wordapp.Quit(ref saveChanges,
               ref originalFormat, ref routeDocument);
  wordapp = null;
  break;
 default:
  Close();
 break;
}

Прежде чем рассматривать приведенный выше код, заметим, что как и при использовании метода Activate в Excel (см.Глава 2., Параграф 10. этого раздела), в данном коде возникает предупреждение компилятора при использовании метода (только в VisualStudio 2005/2008) Quit. Оно выглядит следующим образом:

Warning	1	
Ambiguity between method 'Microsoft.Office.Interop.Word._Application.Quit(ref object, 
 ref object, ref object)' 
and non-method 'Microsoft.Office.Interop.Word.ApplicationEvents4_Event.Quit'. 
Using method group.

Эта двусмысленность в использовании одноименных свойства и метода объявленных в интерфейсе _Application(namespace Microsoft.Office.Interop.Word) и интерфейсе ApplicationEvents4_Event (namespace Microsoft.Office.Interop.Word). Оба эти интерфейса наследует класс объекта:

namespace Microsoft.Office.Interop.Word
{
 [Guid("00020970-0000-0000-C000-000000000046")]
 [CoClass(typeof(ApplicationClass))]
 public interface Application : _Application, ApplicationEvents4_Event
 {
 }
}

И, хотя использование метода Quit не приводит к двусмысленности в выполнении кода, для тех, кто привык писать "чистый код", этот "глюк" лучше устранить. Устранение подобных неудобств можно выполнить через обработчики событий (как это делается мы видели в Главе 2. Параграф 9. этого раздела) или, как рекомендует компилятор, через использование приведения к группе (Using method group). Следующий код не будет давать предупреждения компиляции:

((Word._Application)wordapp).Quit(ref saveChanges,
                             ref originalFormat, ref routeDocument);                        
wordapp = null;

Поскольку этот способ проще, описанного в Главе 2, то будем далее использовать именно его.

Рассмотрим приведенный код создания сервера Word.

Создание объекта Word.Application аналогично тому, как мы это делали в Excel, закрытие же сервера требует использования ряда параметров с ключевым словом ref, которые, как и для многих других методов в Word, должны быть записаны в переменную до передачи в метод. В каждом случае требуется создавать переменную типа Object, присваивать ей значение и использовать эту переменную с ключевым словом ref.

Рассмотрим параметры метода Quit:

  • SaveChanges - определяет как сохраняет Word измененные документы перед осуществлением выхода. Может быть одна из Word.WdSaveOptions констант:

    • wdDoNotSaveChanges - не сохранять,

    • wdPromptToSaveChanges - выдать запрос перед сохранением,

    • wdSaveChanges - сохранить без предупреждения.

В нашем примере мы еще не создали документ и, поэтому, любая константа пока не оказывает влияние на выход. Однако, если в уже в запущенном Word создать документ (обычным для Word способом) и что-то в него записать, то при закрытии Word будет выдан запрос - сохранять или нет документ.

  • OriginalFormat - необязательный параметр, определяет формат сохранения для документа. Возможна одна из следующих констант: Word.WdOriginalFormat констант:

    • wdOriginalDocumentFormat - в оригинальном формате документа (не изменяя его),

    • wdPromptUser - по выбору пользователя (актуально при открытии документа, а не при его создании, при создании и сохранении окно сохранения документа всегда присутствует при отсутствии заданного имени документа).

    • wdWordDocument - формат .doc.

  • RouteDocument - необязательный параметр. При true документ направляется следующему получателю, если документ является attached документом.


    В начало

    Параграф 2. Создание документов

    Как отмечалось, основным в иерархии объектов Word.Application является объект Document. Информация об объектах Document хранится в виде ссылок на открытые документы в свойстве Documents. Книга в приложение может быть добавлена только через добавление ссылки в совокупность Workbooks, а ссылка на открытый документ может быть получена различным образом (по имени, номеру, как ссылка на активный документ).

    Рассмотрим создание двух рабочих документов. Для доступа к документам определим глобально объекты Word.Documents и Word.Document.

    private Word.Documents  worddocuments;
    private Word.Document   worddocument; 
    

    Изменим код в case 1:

    case 1:
     wordapp = new Word.Application(); 
     wordapp.Visible=true;
     Object template = Type.Missing;
     Object newTemplate = false;
     Object documentType = Word.WdNewDocumentType.wdNewBlankDocument;
     Object visible = true; 
     //Создаем документ 1
     wordapp.Documents.Add( 
    ref template, ref newTemplate, ref documentType, ref visible);
     //Меняем шаблон
     template = @"C:\a1.doc";
     //Создаем документ 2 worddocument в данном случае создаваемый объект 
     worddocument=
     wordapp.Documents.Add(  
      ref template, ref newTemplate, ref documentType, ref visible);
    break;
    

    О параметрах, передаваемых в методы Word.Application мы уже говорили, остановимся на методе Add.

    Add(ref object Template,ref object  NewTemplate, ref object DocumentType, 
        ref object Visible);
    

    Параметры метода:

    • Template - имя шаблона, по которому создается новый документ. Если значение не указано, то используется шаблон Normal.dot.

    • NewTemplate - при true новый документ открывается как шаблон. Значение по умолчанию - False.

    • DocumentType - тип документа, может принимать одно из следующих значений констант типа word.WdNewDocumentType:

      • wdNewBlankDocument - документ Word (по умолчанию);

      • wdNewEmailMessage - электронное сообщение;

      • wdNewWebPage - Web-страница.

      • wdNewXMLDocument - XML документ.

    • Visible - видимость документа. При true (по умолчанию) документ отображается.

    В качестве параметра Template методу Add можно определить имя существующего документа или полное имя шаблона. Во втором случае мы привязываемся к пути, по которому инсталлированы приложения MicrosoftOffice, и в этом нет необходимости - тот же эффект достигается если используется параметр по умолчанию (напомним, Type - класс декларации типов, Type.Missing - отсутствие значения или значение по умолчанию. Кроме того, некоторые методы принимают необязательные параметры, которые не поддерживаются в C#, и в этом случае также используется Type.Missing, который является ссылочным типом - reference type). Использование в качестве Template имя существующего файла полезно когда потребуется добавлять какие либо данные в уже существующий документ или бланк.

    В приведенном примере мы использовали для получения доступа к документу возвращаемое значение метода Add. Доступ можно получить и через его номер в массиве Documents:

    case 1:
     wordapp = new Word.Application(); 
     wordapp.Visible=true;
     Object template = Type.Missing;
     Object newTemplate = false;
     Object documentType = Word.WdNewDocumentType.wdNewBlankDocument;
     Object visible = true; 
     wordapp.Documents.Add( 
    ref template, ref newTemplate, ref documentType, ref visible);
     template = @"C:\a1.doc";
     worddocument=
     wordapp.Documents.Add(  
    ref template, ref newTemplate, ref documentType, ref visible);
     Object number = 2; 
     if(wordapp.Documents.Count >= 2)
     {
      //Для Visual Studio 2003
      //worddocument=(Word.Document)wordapp.Documents.Item(ref number);
      //Для Visual Studio 2005/2008
      worddocument = (Word.Document)wordapp.Documents.get_Item(ref number);
      worddocument.Activate();
     }
    

    В данном примере, при работе в Visual Studio 2003 активным становился (как не странно) первый, а не второй из созданных документов (нумерация от 1 в обратном порядке создания). Видно поэтому разработчики ввели метод get_Item(ref number). Но, все же, более удобнее использовать доступ к документу по имени, как показано в следующем примере:

    case 1:
     wordapp = new Word.Application(); 
     wordapp.Visible=true;
     Object template = Type.Missing;
     Object newTemplate = false;
     Object documentType = Word.WdNewDocumentType.wdNewBlankDocument;
     Object visible = true; 
     wordapp.Documents.Add( 
      ref template, ref newTemplate, ref documentType, ref visible);
     template = @"C:\a1.doc";
     wordapp.Documents.Add(  
     ref template, ref newTemplate, ref documentType, ref visible);
     worddocuments=wordapp.Documents;
     Object name="Документ2";
     //Для Visual Studio 2003
     //worddocument=(Word.Document)worddocuments.Item(ref name);
     //Для Visual Studio 2005/2008
     worddocument = (Word.Document)worddocuments.get_Item(ref name);
     worddocument.Activate();
    break;
    


    В начало

    Параграф 3. Сохранение документов

    Документы Word можно сохранить программно и обычным для Word способом. В любом случае перед выходом из Word необходимо вызвать метод Quit. Если свойство Word.Application DisplayAlerts имеет значение true, Word предложит сохранить данные в том случае, когда после старта в документ были внесены какие либо изменения.

    Для сохранения документа можно использовать методы Save(), SaveAs() и SaveAs2000. Метод Save() не имеет параметров и при его вызове будет отображено диалоговое окно Word "Сохранение документа". Напротив, метод SaveAs имеет множество параметров, большинство из которых можно не указывать, а использовать как параметры по умолчанию.

    Рассмотрим параметры методов SaveAs() и SaveAs2000() (они имеют одинаковые параметры, однако при использовании на компьютере Office 2000 или OfficeXP рекомендуется использовать метод SaveAs2000, пример использования см. ниже):

    SaveAs(
      ref fileName,        //Имя файла
      ref fileFormat,      //Формат сохраняемого файла, одна из
                           //Word.WdSaveFormat констант
                           //wdFormatDocument, wdFormatWebArchive, 
                           //wdFormatUnicodeText, w
                           //dFormatTextLineBreaks, wdFormatRTF,
                           //wdFormatText, wdFormatTemplate,  
                           //wdFormatHTML, wdFormatFilteredHTML, 
                           //wdFormatEncodedText, wdFormatDOSText
                           //wdFormatDOSTextLineBreaks,                                 
      ref lockComments,    //При true  блокируется содержимое поля 
                           //Заметки, находящегося на вкладке
                           //Документ в диалоговом окне Свойства 
                           //меню Файл.
      ref password,        //Пароль доступа к документу при открытии
      ref addToRecentFiles,//При true имя сохраняемого файла 
                           //добавляется в список недавно открытых 
                           //файлов в меню Файл.  
      ref writePassword,   //Пароль для внесения изменений в документ
      ref readOnlyRecommended,  //При true - при открытии документа
                                //будет отображаться диалоговое окно
                                //с рекомендацией открывать документ
                                //только для чтения
      ref embedTrueTypeFonts,   //При true - TrueType шрифты сохраняются
                                //вместе с документом
      ref saveNativePictureFormat, //При true сохраняет только родную
                                   //графику (Windows)  
      ref saveFormsData,           //При true сохраняет только данные, 
                                   //введенные пользователем 
                                   //во вводные формы. 
      ref saveAsAOCELetter,  //Если в документе используется 
                             //attached mailer (программа доставки 
                             //электронной почты адресату),
                             //то  true для того чтобы документ был 
                             //сохранен. 
      ref encoding,          //Кодовая страница, или набор символов, 
                             //для документов, сохраненных как 
                             //кодируемые текстовые файлы. 
                             //Значение по умолчанию - системная 
                             //кодовая страница. Задается как
                             //Microsoft.Office.Core.MsoEncoding
                             //.msoEncodingUSASCII;
      ref insertLineBreaks,  //Если документ сохраняется как 
                             //текстовый файл, то при true 
                             //разрешается вставка разрывов строк. 
      ref allowSubstitutions,// Если документ  сохраняется как 
                             //текстовый файл, то при true,  Word 
                             //заменяет некоторые символы 
                             //текстом. Например, символ авторского 
                             //права как (c).                         
      ref lineEnding,        //Если документ сохраняется как 
                             //текстовый файл, то одна из  
                             //Word.WdLineEndingType констант (wdCRLF,
                             //wdLSPS,wdCROnly, wdLFCR,wdLFOnly, 
                             //определяющих какие символы (перевод 
                             //строки, возврат каретки) используются 
                             //для отделения строк друг от друга.
      ref addBiDiMarks       //При true,  Word  добавляет к файлу 
                             //символы управления  вывода, чтобы 
                             //сохранить двунаправленное размещение 
                             //текста в оригинале документа.
    );
    

    Добавим к предыдущему примеру функцию сохранения и сохраним открытый документ a1.doc с именем a2.doc (на данном этапе можно поэксперементировать и с сохранением документа как текстового файла для формата wdFormatText и уяснить на примерах действие последних из рассмотренных параметров, которые в принципе повторяют установки окна преобразования файла см. Рис.4).

    wordexce0303.gif

    Рис.4. Окно преобразования файла.

    case 1: 
     wordapp = new Word.Application(); 
     wordapp.Visible=true;
     Object template = Type.Missing;
     Object newTemplate = false;
     Object documentType = Word.WdNewDocumentType.wdNewBlankDocument;
     Object visible = true;  
     wordapp.Documents.Add( 
     ref template, ref newTemplate, ref documentType, ref visible);
     template = @"C:\a1.doc";
     worddocument=
     wordapp.Documents.Add(  
     ref template, ref newTemplate, ref documentType, ref visible);
    
     worddocuments=wordapp.Documents;
     Object name="Документ2";
     //Для Visual Studio 2003
     //worddocument=(Word.Document)worddocuments.Item(ref name);
     worddocument = (Word.Document)worddocuments.get_Item(ref name);
     worddocument.Activate();
     //Подготавливаем параметры для сохранения документа
     Object fileName = @"C:\a2.doc";
     Object fileFormat = Word.WdSaveFormat.wdFormatDocument;
     Object lockComments = false;
     Object password = "";
     Object addToRecentFiles = false;
     Object writePassword = "";
     Object readOnlyRecommended = false;
     Object embedTrueTypeFonts = false;
     Object saveNativePictureFormat = false;
     Object saveFormsData = false;
     Object saveAsAOCELetter = Type.Missing;
     Object encoding = Type.Missing;
     Object insertLineBreaks = Type.Missing;
     Object allowSubstitutions = Type.Missing;
     Object lineEnding = Type.Missing;
     Object addBiDiMarks = Type.Missing;
     #if OFFICEXP
       worddocument.SaveAs2000(ref fileName,
     #else
      worddocument.SaveAs(ref fileName,
     #endif
     ref fileFormat, ref lockComments, 
     ref password, ref addToRecentFiles, ref writePassword, 
     ref readOnlyRecommended, ref embedTrueTypeFonts, 
     ref saveNativePictureFormat, ref saveFormsData, 
     ref saveAsAOCELetter, ref encoding, ref insertLineBreaks, 
     ref allowSubstitutions, ref lineEnding, ref addBiDiMarks);
    break;
    

    Того же эффекта можно было добиться задав значения всех параметров (кроме имени файла) как Type.Missing.


    В начало

    Параграф 4. Открытие существующего документа

    Для открытия существующего документа основными методом является метод Open (Open2000, Open2002).

    Рассмотрим параметры метода Open. Методы Open2000, Open2002 имеют те же параметры, что и метод Open, но параметров у данных методов меньше. Этими методами рекомендуется пользоваться только при разработке приложений под конкретную версию Office (например, при использовании на компьютере Office 2000 или OfficeXP рекомендуется использовать метод Open2000).

    Синтаксис метода:

    Open(
    ref FileName,           //Имя открываемого файла включая полный путь
    ref ConfirmConversions, //При true в случае открытия документа не формата Word 
                            //будет выводится диалоговое окно конвертирования файла. 
    ref  ReadOnly,          //При true документ открывается только для чтения
    ref  AddToRecentFiles,  //При true имя открываемого файла добавляется
                            //в список недавно открытых файлов в меню Файл.  
    ref  PasswordDocument,  //Пароль открываемого документа если он есть
    ref  PasswordTemplate,  //Пароль шаблона документа если он есть
    ref  Revert,            //При true возможно повторное открытие экземпляра 
                            //того же документа с потерей изменений в открытом ранее.
                            //При false новый экземпляр не открывается.
    ref  WritePasswordDocument,//Пароль для сохранения документа 
    ref  WritePasswordTemplate,//Пароль для сохранения шаблона 
    ref  Format,            //Одна из следующих Word.WdOpenFormat констант
                            //wdOpenFormatAllWord, wdOpenFormatAuto, 
                            //wdOpenFormatDocument,  wdOpenFormatEncodedText,
                            //wdOpenFormatRTF, wdOpenFormatTemplate, 
                            //wdOpenFormatText, wdOpenFormatUnicodeText
                            // или wdOpenFormatWebPages. 
                            //По умолчанию wdOpenFormatAuto.
    ref  Encoding,          //Кодовая страница, или набор символов, 
                            //(кодировка) для просмотра документа,
                            //Значение по умолчанию - системная 
                            //кодовая страница. Задается как
                            //Microsoft.Office.Core.MsoEncoding.msoEncodingUSASCII;
    ref  Visible,           //При true документ открывается как видимый. 
    ref  OpenAndRepair,     //При true делается попытка восстановить поврежденный
                            //документ.
    ref  DocumentDirection, //Направление текста - одна из Word.WdDocumentDirection
                            // констант: WdLeftToRight, WdRightToLeft.
    ref  NoEncodingDialog,  //При true подавляется показ диалогового окна
                            //Encoding, которое отображается если кодировка 
                            //не распознана.
    ref  xmlTransform       //Определяет тип XML данных при XML преобразованиях 
    ) 
    

    В методе все параметры кроме имени файла могут иметь значение Type.Missing, то есть иметь значения по умолчанию, соответствующее открытию простого документа Word.

    Пример открытия существующего документа:

    case 1:
     wordapp = new Word.Application(); 
     wordapp.Visible=true;
     Object filename = @"C:\a1.doc";
     Object confirmConversions = true;
     Object readOnly = false;
     Object addToRecentFiles = true;
     Object passwordDocument = Type.Missing;
     Object passwordTemplate = Type.Missing;
     Object revert = false;
     Object writePasswordDocument = Type.Missing;
     Object writePasswordTemplate = Type.Missing;
     Object format = Type.Missing;
     Object encoding = Type.Missing;;
     Object oVisible = Type.Missing;
     Object openConflictDocument = Type.Missing;
     Object openAndRepair  = Type.Missing;
     Object documentDirection = Type.Missing;
     Object noEncodingDialog = false;
     Object xmlTransform = Type.Missing;
     //#if OFFICEXP
     //  worddocument=wordapp.Documents.Open2000(ref filename, .....
     //#else
       worddocument=wordapp.Documents. Open(ref filename,     
     //#endif 
      ref confirmConversions, ref readOnly, ref addToRecentFiles, 
      ref passwordDocument, ref passwordTemplate, ref revert, 
      ref writePasswordDocument, ref writePasswordTemplate, 
      ref format, ref encoding, ref oVisible,  
      ref openAndRepair , ref documentDirection, ref noEncodingDialog,ref xmlTransform);
    break;
    


    В начало

    Параграф 5. Вывод текстовой информации - объект и свойство Range

    Создадим или откроем документ Word, например как в предыдущем примере. Объект worddocument на данном этапе соответствует объекту открытого документа и необходим нам для того, чтобы еще ниже опуститься по иерархии объектов Word. Следующим в иерархии объектов рассмотрим Word.Paragraph - параграф. Текстовая информация помещается и хранится в параграфах документа Word (объект Paragraph это один абзац текста).

    Для манипуляции с параграфами определим глобально соответствующие объекты:

    private Word.Paragraphs wordparagraphs;
    private Word.Paragraph  wordparagraph;
    

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

    wordparagraphs=worddocument.Paragraphs;
    Text=Convert.ToString(wordparagraphs.Count);
    

    Вывод текста выполняется не просто в параграф, а в диапазон параграфа - объект Range. Объект Range - это непрерывная область документа, включающая позицию начального и конечного символов. Для пустого параграфа или если начальная и конечная позиции диапазона совпадают - Range представляет курсор ввода.

    В документе можно определить диапазон, вызовом метода Range с передачей ему начального и конечного значений позиций символов (при определении позиции номера символов считаются от 0 и включают все символы, в том числе и не печатные). Выделенный диапазон можно "подсветить", используя метод Select().

    Object begin = 0;
    Object end   = 5;
    Word.Range wordrange = worddocument.Range(ref begin, ref end);
    wordrange.Select();
    

    Есть возможность выделить весь текст всего документа следующим образом:

    Object begin = Type.Missing;
    bject end   = Type.Missing;
    Word.Range wordrange = worddocument.Range(ref begin, ref end);
    wordrange.Select();
    

    Объект Range позволяет выполнить вывод текста в выделенный участок и изменить параметры текста (шрифт, цвет, подчеркивание....).

    wordrange.Font.Size=12;
    wordrange.Font.Color=Word.WdColor.wdColorRed;
    wordrange.Text="Текст который мы выводим в выделенный участок "; 
    

    Помимо этого имеется возможность программно создать свой стиль и применить его либо ко всему документу, либо к объекту Range. Все возможности форматирования текста можно посмотреть в меню Word "Формат" пункт "Стили и форматирование". Изменять можно шрифт документа, параметры абзаца, параметры табуляции, границы, язык, рамки, нумерацию, сочетание клавиш. Они все доступны и программно за исключением возможности сохранять в шаблоне Word свой созданный стиль.

    Принцип работы со стилями демонстрирует следующий фрагмент кода:

    //Определяем для чего создается стиль: wdStyleTypeTable, 
    //wdStyleTypeList, wdStyleTypeParagraph, wdStyleTypeCharacter
    object patternstyle=Word.WdStyleType.wdStyleTypeParagraph;
    //Создаем стиль
    Word.Style wordstyle=worddocument.Styles.Add("myStyle",ref patternstyle);
    //Устанавливаем параметры шрифта
    wordstyle.Font.Size=30;
    wordstyle.Font.Italic=1;
    wordstyle.Font.Bold=1;
    ......
    //Устанавливаем параметры параграфа
    wordstyle.ParagraphFormat.LeftIndent
     =worddocument.Content.Application.CentimetersToPoints((float)2);
    wordstyle.ParagraphFormat.RightIndent
     =worddocument.Content.Application.CentimetersToPoints((float)2);
    ......
    //И.т.д. пока не будут выставлены все необходимые параметры
    //Устанавливаем стиль для документа
    object begin = Type.Missing;
    Object end   = Type.Missing;
    Word.Range wordrange =worddocument.Range(ref begin, ref end);
    object oWordStyle=wordstyle;
    wordrange.set_Style(ref oWordStyle); 
    

    Шрифт и другие параметры форматирования текста можно задать как параметры по умолчанию для всего документа аналогично заданию стиля:

    worddocument.Content.Font.Size=25;
    worddocument.Content.Font.Bold=1;
    worddocument.Content.Font.Underline=Word.WdUnderline.wdUnderlineSingle;
    worddocument.Content.ParagraphFormat.Alignment=
    Word.WdParagraphAlignment.wdAlignParagraphCenter;
    worddocument.Content.ParagraphFormat.LeftIndent=
     worddocument.Content.Application.CentimetersToPoints((float)2);
    worddocument.Content.ParagraphFormat.RightIndent=
     worddocument.Content.Application.CentimetersToPoints((float)1);
    .....
    

    Свойства Content объекта Document определяет основную область документа (document's main story), т. е. его содержимое без колонтитулов и других вспомогательных элементов.

    Кроме объекта Range документа каждый параграф также имеет свойство Range, которое позволяет выводить текст и устанавливать его характеристики для параграфа.

    Следующий пример демонстрирует возможности вывода текста используя свойство Range параграфа и объект Range документа (для демонстрации лучше код примера добавлять начиная с вывода 1го абзаца и т.д.):

    case 1:
     wordapp = new Word.Application(); 
     wordapp.Visible=true;
     //Открываем существующий документ
     Object filename = @"C:\a1.doc";
     Object confirmConversions = true;
     Object readOnly = false;
     Object addToRecentFiles = true;
     Object passwordDocument = Type.Missing;
     Object passwordTemplate = Type.Missing;
     Object revert = false;
     Object writePasswordDocument = Type.Missing;
     Object writePasswordTemplate = Type.Missing;
     Object format = Type.Missing;
     Object encoding = Type.Missing;;
     Object oVisible = Type.Missing;
     Object openConflictDocument = Type.Missing;
     Object openAndRepair  = Type.Missing;
     Object documentDirection = Type.Missing;
     Object noEncodingDialog = false; 
     Object xmlTransform = Type.Missing;
      worddocument=wordapp.Documents. Open(ref filename,     
      ref confirmConversions, ref readOnly, ref addToRecentFiles, 
      ref passwordDocument, ref passwordTemplate, ref revert, 
      ref writePasswordDocument, ref writePasswordTemplate, 
      ref format, ref encoding, ref oVisible,  
      ref openAndRepair , ref documentDirection, ref noEncodingDialog,
    	ref xmlTransform);
      //Получаем ссылки на параграфы документа
      wordparagraphs=worddocument.Paragraphs;
      //Будем работать с первым параграфом
      wordparagraph=(Word.Paragraph)wordparagraphs[1];
      //Выводим текст в первый параграф
      wordparagraph.Range.Text="Текст который мы выводим в 1 абзац"; 
      //Меняем характеристики текста и параграфа
      wordparagraph.Range.Font.Color=Word.WdColor.wdColorBlue;
      wordparagraph.Range.Font.Size=20;
      wordparagraph.Range.Font.Name="Arial";
      wordparagraph.Range.Font.Italic=1;
      wordparagraph.Range.Font.Bold=0;
      wordparagraph.Range.Font.Underline=Word.WdUnderline.wdUnderlineSingle;
      wordparagraph.Range.Font.UnderlineColor=Word.WdColor.wdColorDarkRed;
      //wordparagraph.Range.Font.StrikeThrough=1; можно перечеркнуть
      //Выравнивание
      wordparagraph.Alignment=Word.WdParagraphAlignment.wdAlignParagraphCenter;
      //Добавляем в документ несколько параграфов
      object oMissing = System.Reflection.Missing.Value;
      worddocument.Paragraphs.Add(ref oMissing);
      worddocument.Paragraphs.Add(ref oMissing);
      worddocument.Paragraphs.Add(ref oMissing);
      worddocument.Paragraphs.Add(ref oMissing);
      worddocument.Paragraphs.Add(ref oMissing);
      wordparagraph.Range.Text=
        "Текст который мы выводим в последний добавленный абзац"; 
      wordparagraph=(Word.Paragraph)wordparagraphs[3];
      wordparagraph.Range.Text=
           "Текст который мы выводим в третий абзац";
      //Использование объекта Range для всего документа
      Object begin = 42;
      Object end   = 49;
      Word.Range wordrange = worddocument.Range(ref begin, ref end);
      wordrange.Select();
      //На Рис.5. Слева выведенный  текст на данном этапе
      //Меняем характеристики текста выделенного фрагмента
      wordrange.Font.Size=12;
      wordrange.Font.Color=Word.WdColor.wdColorRed;
      wordrange.Text="Текст который мы выводим в выделенный участок "; 
      //На Рис.5. Справа выведенный текст на данном этапе
    break;
    

    wordexce0304.gif

    Рис.5. Вывод текстовой информации.

    Обратим внимание, что при использовании объекта Range вставляемый в выделенную область текст заменяет выделенный фрагмент и переносится в него полностью - не зависимо от величины диапазона.


    В начало

    Параграф 6. Вывод текстовой информации - объект Selection

    Объект Selection представляет собой текущую выделенную область документа. Все действия, связанные с внесением в документ каких либо частных изменений в Word выполняются применительно к выделенным фрагментам. Программно это выполняется через объект Selection. Аналогично, как и при обычной работе с Word, при программном выводе необходимо вначале выделить фрагмент и, далее, выполнить требуемые действия над данным фрагментом (изменить шрифт, форматирование, напечатать и т.д.).

    Объект Selection всегда присутствует в документе. Если ничего не выделено, он представляет курсор ввода (insertion point).

    Для демонстрации использования объекта Selection сохраним в файле C:\a1.doc результаты выполнения кода предыдущего примера (Рис.4.).

    Объект Selection может представлять блок, строку или столбец таблицы, курсор ввода, рисунок, фрейм, выделенный текст, или некоторую комбинацию объектов, которые можно определить через свойство Type объекта Selection (wdSelectionBlock, wdSelectionRow, wdSelectionColumn, wdSelectionIP, wdSelectionShape, wdSelectionInlineShape, wdSelectionNormal). Посколько свойства и методы у различных типов объектов Selection различны, то при применении того или иного метода или использования свойства рекомендуется выполнить проверку типа объекта Selection, например:

    if(wordapp.Selection.Type == Word.WdSelectionType.wdSelectionNormal)
    {
     //Работаем с текстом
    }
    

    При выводе и форматировании текста прежде всего требуется не определить, что в данный момент представляет объект Selection, а задать его (например, выделить строку, слово, часть слова и т.п.). Для задания выделения требуется выполнять действия по перемещению курсора, для чего используются методы, выполняющие, как и в обычном Word, те или иные действия по перемещению курсора:

    • Методы, применение которых аналогично нажатию клавиши Home и End на клавиатуре:

      • HomeKey([Unit], [Extend]);

      • EndKey([Unit], [Extend]);

    • Методы, имитирующие действие клавиш со стрелками:

      • MoveLeft([Unit], [Count], [Extend]);

      • MoveRight([Unit], [Count], [Extend]);

      • MoveUp([Unit], [Count], [Extend]);

      • MoveDown([Unit], [Count], [Extend]).

    • Метод Move([Unit], [Count]);

    Рассмотрим эти методы.


    В начало

    6.1. Методы HomeKey и EndKey

    HomeKey([Unit], [Extend]);
    EndKey([Unit], [Extend]);
    

    Аргумент Unit может принимать одно из значений Word.WdUnitsWord:

    • WdLine - переход в начало (конец) строки. Значение по умолчанию.

    • WdStory - переход в начало (конец) документа.

    • WdColumn - переход в начало (конец) столбца таблицы.

    • WdRow - переход в начало (конец) строки таблицы.

    Аргумент Extend указывается одно из значений Word.WdMovementType.

    • WdMove - только переместить курсор. При использовании с wdLine перемещает курсор ввода в начало или конец строки, а при использовании с wdStory - в начало или конец документа.

    • WdExtend - выделяет фрагмент от курсора ввода до некоторой конечной позиции. Например, если курсор ввода находится в начале документа, то EndKey при значении параметра Unit равным wdStory и значении Extend равным wdExtend выделит весь текст. В общем случае значение Extend равное wdExtend соответствует нажатию клавиш Ctrl+Home иCtrl+End для параметра Unit WdLine Ctrl+Shift+Home и Ctrl+Shift+End для параметра Unit wdStory.

    Пример использования методов HomeKey и EndKey для выделения всего текста.

    case 1:
     wordapp = new Word.Application(); 
     wordapp.Visible=true;
     Object filename = @"C:\a1.doc";
     Object confirmConversions = true;
     Object readOnly = false;
     Object addToRecentFiles = true;
     Object passwordDocument = Type.Missing;
     Object passwordTemplate = Type.Missing;
     Object revert = false;
     Object writePasswordDocument = Type.Missing;
     Object writePasswordTemplate = Type.Missing;
     Object format = Type.Missing;
     Object encoding = Type.Missing;;
     Object oVisible = Type.Missing;
     Object openConflictDocument = Type.Missing;
     Object openAndRepair  = Type.Missing;
     Object documentDirection = Type.Missing;
     Object noEncodingDialog = false; 
     Object xmlTransform = Type.Missing;
     worddocument=wordapp.Documents. Open(ref filename,     
      ref confirmConversions, ref readOnly, ref addToRecentFiles, 
      ref passwordDocument, ref passwordTemplate, ref revert, 
      ref writePasswordDocument, ref writePasswordTemplate, 
      ref format, ref encoding, ref oVisible,  
      ref openAndRepair , ref documentDirection, ref noEncodingDialog,
      ref xmlTransform);
      //Непосредственно  работа с объектом Selection
     object unit; 
     object count; 
     object extend; 
     //Курсор ввода устанавливается в начало документа
     unit = Word.WdUnits.wdStory; 
     extend = Word.WdMovementType.wdMove; 
     wordapp.Selection.HomeKey(ref unit, ref extend); 
     //Выделяется текст до конца документа 
     unit = Word.WdUnits.wdStory; 
     extend = Word.WdMovementType.wdExtend; 
     wordapp.Selection.EndKey(ref unit, ref extend); 
    break;
    


    В начало

    6.2. Методы MoveLeft и MoveRight

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

    MoveLeft([Unit], [Count], [Extend]). 
    MoveRight([Unit], [Count], [Extend]). 
    

    Аргумент Unit может принимать одно из значений Word.WdUnitsWord:

    • wdCharacter - инкремент в единицах символов.

    • wdWord - инкремент в единицах слов.

    • wdCell - инкремент в единицах ячеек таблицы.

    • wdSentence - инкремент в единицах предложений.

    Аргумент Extend указывается одно из значений Word.WdMovementType.

    • WdMove - только переместить курсор. При использовании с wdLine перемещает курсор ввода в начало или конец строки, а при использовании с wdStory - в начало или конец документа.

    • WdExtend - выделяет фрагмент от курсора ввода до конечной позиции, определяемой параметром Count и единицей Word.WdUnitsWord.

    Пример использования методов MoveLeft и MoveRight (фрагмент кода вставлен в предыдущей пример после комментария "Непосредственно работа с объектом Selection"). Результат выполнения кода показан на Рис.6.

    //Непосредственно  работа с объектом Selection
     object unit; 
     object count; 
     object extend; 
     //Курсор ввода устанавливается в начало документа
     unit = Word.WdUnits.wdStory; 
     extend = Word.WdMovementType.wdMove; 
     wordapp.Selection.HomeKey(ref unit, ref extend); 
     //Перемещаем курсор ввода влево на 6 символов
     unit = Word.WdUnits.wdCharacter;
     extend = Word.WdMovementType.wdMove;
     count = 13;
     wordapp.Selection.MoveRight(ref unit, ref count, 
    ref extend);
     unit = Word.WdUnits.wdWord;
     count = 1;
     extend = Word.WdMovementType.wdExtend;
     wordapp.Selection.MoveLeft(ref unit, ref count, 
    ref extend);
    

    wordexce0305.gif

    Рис.6. Пример использования методов MoveLeft и MoveRight


    В начало

    6.3. Методы MoveUp и MoveDown

    Методы позволяют перемещать курсор на указанное число и выделять в тексте указанное число строк или абзацев.

    Аргумент Unit может принимать одно из значений Word.WdUnitsWord:

    • wdLine - инкремент в единицах строк.

    • wdParagraph - инкремент в абзацах.

    • wdWindow - инкремент в единицах окна.

    • wdScreen - инкремент в единицах экрана.

    Остальные параметры аналогичны методам MoveLeft и MoveRight.

    Пример выделения всего текста

    //Непосредственно  работа с объектом Selection
    object unit; 
    object count; 
    object extend; 
    //Курсор ввода устанавливается в начало документа
    unit = Word.WdUnits.wdStory; 
    extend = Word.WdMovementType.wdMove; 
    wordapp.Selection.HomeKey(ref unit, ref extend); 
    //Выделяется текст до конца документа 
    unit = Word.WdUnits.wdWindow;
    extend = Word.WdMovementType.wdExtend;
    count = 1;
    wordapp.Selection.MoveDown(ref unit, ref count, 
    ref extend);
    


    В начало

    6.4. Метод Move

    Метод Move сворачивает выделение к последнему выделенному символу и перемещает курсор ввода на заданное параметром Count число символов, слов, строк, абзацев.

    Метод Move([Unit], [Count]); 
    

    Аргумент Unit может принимать одно из значений Word.WdUnitsWord:

    • wdCharacter - инкремент в единицах символов.

    • wdWord - инкремент в единицах слов.

    • wdLine - инкремент в единицах строк.

    • wdParagraph - инкремент в абзацах.


    В начало

    6.5. Вывод текста

    Для вывода текста с использованием объекта Selection используется его свойство Text или метод объекта TypeText. Метод, в зависимости от того, установлен в Word режим "вставка" или "замена" вставляет или пишет новый текст поверх имеющегося.

    Примеры вывода текста приводятся ниже. В данных примерах сначала создаются и заполняются одинаковым шрифтом четыре абзаца, а затем в режиме вставки вставляется текст с использованием метода TypeText и свойства Text. Пример наглядно демонстрирует (Рис.7.) одинаковый характер действия при применении метода и свойства когда объект Selection представляет выделенный участок текста (строки 1 и 2) и различие при применении если он является курсором ввода (строки 3 и 4).

    //Непосредственно  работа с объектом Selection
    //Устанавливаем шрифт по умолчанию
    worddocument.Content.Font.Size=25;
    worddocument.Content.Font.Bold=1;
    worddocument.Content.Font.Underline=Word.WdUnderline.wdUnderlineSingle;
    worddocument.Content.ParagraphFormat.Alignment=
    Word.WdParagraphAlignment.wdAlignParagraphCenter;
    worddocument.Content.ParagraphFormat.LeftIndent=
     worddocument.Content.Application.CentimetersToPoints((float)2);
    worddocument.Content.ParagraphFormat.RightIndent=
     worddocument.Content.Application.CentimetersToPoints((float)1);
    object unit; 
    object count; 
    object extend; 
    //Курсор ввода устанавливается в начало документа
    unit = Word.WdUnits.wdStory; 
    extend = Word.WdMovementType.wdMove; 
    wordapp.Selection.HomeKey(ref unit, ref extend);
    //Добавляем параграфы и выводим в них текст
    wordapp.Selection.TypeParagraph();
    wordapp.Selection.TypeText("Текст  1 абзаца");
    wordapp.Selection.TypeParagraph();
    wordapp.Selection.TypeText("Текст  2 абзаца");
    wordapp.Selection.TypeParagraph();
    wordapp.Selection.TypeText("Текст  3 абзаца");
    wordapp.Selection.TypeParagraph();
    wordapp.Selection.TypeText("Текст  4 абзаца");
    wordapp.Selection.TypeParagraph();
    //Курсор ввода устанавливается в начало документа
    wordapp.Selection.HomeKey(ref unit, ref extend); 
    //Перемещаем курсор ввода вправо на 6 символов
    unit = Word.WdUnits.wdCharacter;
    extend = Word.WdMovementType.wdMove;
    count = 6;
    wordapp.Selection.MoveRight(ref unit, ref count, 
    ref extend);
    //Выделяем второе слово абзаца
    unit = Word.WdUnits.wdWord;
    count = 1;
    extend = Word.WdMovementType.wdExtend;
    wordapp.Selection.MoveRight(ref unit, ref count, 
    ref extend);
    wordapp.Selection.Font.Size=15;
    wordapp.Selection.Font.Color=Word.WdColor.wdColorRed;
    //Задаем режим вставки
    wordapp.Options.Overtype = false;
    wordapp.Selection.Font.Italic=0;
    wordapp.Selection.Font.Bold=1;
    wordapp.Selection.Font.Underline=Word.WdUnderline.wdUnderlineNone;
    wordapp.Selection.TypeText(" Новый текст 1 ");
    //Переносим курсор ввода ко второму абзацу
    unit = Word.WdUnits.wdParagraph; 
    count = 1;
    wordapp.Selection.Move(ref unit,ref count);
    //Повторяем все, что было сделано для выделения второго слова абзаца
    unit = Word.WdUnits.wdCharacter;
    extend = Word.WdMovementType.wdMove;
    count = 6;
    wordapp.Selection.MoveRight(ref unit, ref count, 
    ref extend);
    //Выделяем второе слово 2 абзаца
    unit = Word.WdUnits.wdWord;
    count = 1;
    extend = Word.WdMovementType.wdExtend;
    wordapp.Selection.MoveRight(ref unit, ref count, 
    ref extend);
    //Задаем те же характеристики форматирования
    wordapp.Selection.Font.Size=15;
    wordapp.Selection.Font.Color=Word.WdColor.wdColorRed;
    wordapp.Options.Overtype = false;
    wordapp.Selection.Font.Italic=0;
    wordapp.Selection.Font.Bold=1;
    wordapp.Selection.Font.Underline=Word.WdUnderline.wdUnderlineNone;
    //Используем свойство Text объекта Selection
    wordapp.Selection.Text=" Новый текст 2 ";
    //Переносим курсор ввода к третьему абзацу
    unit = Word.WdUnits.wdParagraph; 
    count = 1;
    wordapp.Selection.Move(ref unit,ref count);
    //Только сдвигаем курсор ввода - бег выделения текста
    unit = Word.WdUnits.wdCharacter;
    extend = Word.WdMovementType.wdMove;
    count = 6;
    wordapp.Selection.MoveRight(ref unit, ref count, 
    ref extend);
    //Задаем теже характеристики форматирования
    wordapp.Selection.Font.Size=15;
    wordapp.Selection.Font.Color=Word.WdColor.wdColorRed;
    wordapp.Options.Overtype = false;
    wordapp.Selection.Font.Italic=0;
    wordapp.Selection.Font.Bold=1;
    wordapp.Selection.Font.Underline=Word.WdUnderline.wdUnderlineNone;
    //Используем свойство Text объекта Selection
    wordapp.Selection.TypeText(" Новый текст 3" );
    //Переносим курсор ввода к четвертому абзацу
    unit = Word.WdUnits.wdParagraph; 
    count = 1;
    wordapp.Selection.Move(ref unit,ref count);
    //Только сдвигаем курсор ввода - бег выделения текста
    unit = Word.WdUnits.wdCharacter;
    extend = Word.WdMovementType.wdMove;
    count = 6;
    wordapp.Selection.MoveRight(ref unit, ref count, 
    ref extend);
    //Задаем теже характеристики форматирования
    wordapp.Selection.Font.Size=15;
    wordapp.Selection.Font.Color=Word.WdColor.wdColorRed;
    wordapp.Options.Overtype = false;
    wordapp.Selection.Font.Italic=0;
    wordapp.Selection.Font.Bold=1;
    wordapp.Selection.Font.Underline=Word.WdUnderline.wdUnderlineNone;
    //Используем свойство Text объекта Selection
    wordapp.Selection.Text=" Новый текст 4";
    

    wordexce0306.gif

    Рис.7. Пример вывода текста


    В начало

    Параграф 7. Работа с таблицами


    В начало

    7.1. Создание таблиц

    Информация об объектах Table хранится в виде ссылок на таблицы документа в свойстве Tables. Набор ссылок Tables доступен из объектов Document, Selection и Range и даже из объекта Word.Table. Это значит, что и создавать таблицы можно с использованием любого из этих объектов (в любом - применительно к таблицам). Для создания таблиц используется метод Add:

    Add(
    Word.Range Range, //Объект Range - место формирования таблицы
    int NumRows,      //Число строк
    int NumColumns,   //Число столбцов
    ref object DefaultTableBehavior,//Определяет, изменяет ли Word 
                                    //автоматически размеры ячеек в 
                                    //таблицах, чтобы они  соответствовали 
                                    //содержанию  ячеек. Может быть 
                                    //одна из Word.WdDefaultTableBehavior 
                                    //констант: wdWord8TableBehavior (нет) 
                                    //или wdWord9TableBehavior (да). 
                                    //По умолчанию - wdWord8TableBehavior. 
    ref object AutoFitBehavior      //Автоподбор ширины столбцов
                                    //одна из следующих Word.WdAutoFitBehavior
                                    //констант: wdAutoFitContent - по 
                                    //содержимому, wdAutoFitFixed -
                                    //фиксированная или wdAutoFitWindow
                                    //по ширине окна. Если DefaultTableBehavior
                                    //установлен в wdWord8TableBehavior, 
                                    //этот параметр игнорируется.
    )
    

    Пример создания таблицы:

    //Таблицу вставляем в начало документа
    Object start = 0;
    Object end = 0;
    Word.Range wordrange = worddocument.Range(ref start, ref end);
    Object defaultTableBehavior = 
       Word.WdDefaultTableBehavior.wdWord9TableBehavior;
    Object autoFitBehavior = Word.WdAutoFitBehavior.wdAutoFitWindow;
    //Добавляем таблицу и получаем объект wordtable 
    Word.Table wordtable = worddocument.Tables.Add(wordrange, 5, 5, 
                      ref defaultTableBehavior, ref autoFitBehavior);
    

    После того как таблица добавлена в документ, объект, соответствующий добавленной таблице можно получить по ее номеру в порядке добавления:

    Word.Table wordtable = worddocument.Tables[1];
    

    После того как мы добавили таблицу и получили объект Word.Table мы можем изменить стиль таблицы, например:

    Object style = "Классическая таблица 1";
    wordtable.set_Style(ref style);
    //Далее можно добавлять выделение первых
    //и последних строк и столбцов
    wordtable.ApplyStyleFirstColumn=true;
    wordtable.ApplyStyleHeadingRows=true;
    wordtable.ApplyStyleLastRow=false;
    wordtable.ApplyStyleLastColumn=false;
    

    Пример создания двух таблиц (Рис.8.). В примере не только показано как можно создать таблицу, но и как разместить ее в пределах документа Word. Пример, как и ранее, выполняется при открытии чистого документа C:\a.doc, и, поэтому, здесь опускается часть кода, приводимая выше по открытию документа:

    case 1:
    
    .......... 
    
     //Вставляем в документ 4 параграфа
     object oMissing = System.Reflection.Missing.Value;
     worddocument.Paragraphs.Add(ref oMissing);
     worddocument.Paragraphs.Add(ref oMissing);
     worddocument.Paragraphs.Add(ref oMissing);
     worddocument.Paragraphs.Add(ref oMissing);
     //Переходим к первому добавленному параграфу
     wordparagraph=worddocument.Paragraphs[2];
     Word.Range wordrange=wordparagraph.Range;
     //Добавляем таблицу в начало второго параграфа
     Object defaultTableBehavior = 
      Word.WdDefaultTableBehavior.wdWord9TableBehavior;
     Object autoFitBehavior = 
      Word.WdAutoFitBehavior.wdAutoFitWindow;
     Word.Table wordtable1 = worddocument.Tables.Add(wordrange, 5, 5, 
       ref defaultTableBehavior,ref autoFitBehavior);
     //Сдвигаемся вниз в конец документа
     object unit; 
     object extend; 
     unit = Word.WdUnits.wdStory; 
     extend = Word.WdMovementType.wdMove; 
     wordapp.Selection.EndKey(ref unit, ref extend); 
     //Вставляем таблицу по месту курсора
     Word.Table wordtable2 = worddocument.Tables.Add(
       wordapp.Selection.Range, 4, 4, ref defaultTableBehavior,
     ref autoFitBehavior);
     //Меняем стили созданных таблиц
     Object style = "Классическая таблица 1";
     wordtable1.set_Style(ref style);
     style = "Сетка таблицы 3";
     Object applystyle = true;
     wordtable2.set_Style(ref style);
     wordtable2.ApplyStyleFirstColumn=true;
     wordtable2.ApplyStyleHeadingRows=true;
     wordtable2.ApplyStyleLastRow=false;
     wordtable2.ApplyStyleLastColumn=false;
    break;
    

    wordexce0307.gif

    Рис.8. Пример создания таблиц

    Обратим внимание на то, что курсор остался в первой ячейки последней добавленной таблицы. Это может понадобиться для начала вывода информации.


    В начало

    7.2. Вывод информации в ячейки таблиц

    Таблица или Объект Word.Tableт состоит из ячеек - объектов Cell, ссылки на которые хранятся в наборе Cells данной таблицы. Ячейки таблицы считаются упорядоченными по координатам X и Y, нумерация с 1. Следующие строки кода ссылаются на ячейку, расположенную в первой строке и во втором столбце:

    Word.Range wordcellrange = worddocument.Tables[1].Cell(1, 2).Range;
    wordcellrange=wordtable2.Cell(2,3).Range;
    

    Для вывода текста в ячейку достаточно свойству Text объекта Word.Range присвоить значение типа string.

    wordcellrange.Text="Строка для вывода";
    

    Добавим к приведенному выше коду примера следующие строки и продемонстрируем вывод текста в ячейки (Рис.9.):

    Word.Range wordcellrange = worddocument.Tables[1].Cell(1, 2).Range;
    wordcellrange.Text="Ячейка 1 2";
    wordcellrange=wordtable2.Cell(2, 3).Range;
    wordcellrange.Text="Ячейка 2 3";
    for(int m=0; m < wordtable2.Rows.Count; m++)   
     for(int n=0; n < wordtable2.Columns.Count; n++)
     {
      wordcellrange = wordtable2.Cell(m+1, n+1).Range;
      wordcellrange.Text = "Ячейка"+Convert.ToString(m+1)+" "
                               +Convert.ToString(n+1);
    } 
    

    wordexce0308.gif

    Рис.9. Вывод текста в ячейки таблиц

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

    wordcellrange.Font.Size=(m+1)*5;
    

    Задать цвет шрифта можно следующими способами:

    wordcellrange.Font.ColorIndex=Word.WdColorIndex.wdBlue;
    wordcellrange.Font.Color=Word.WdColor.wdColorDarkRed;
    

    Аналогично можно задать и обводку ячеек:

    wordcellrange.Borders[Word.WdBorderType.wdBorderBottom].LineStyle =
      Word.WdLineStyle.wdLineStyleTriple;
    wordcellrange.Borders[Word.WdBorderType.wdBorderLeft].Color =
      Word.WdColor.wdColorDarkYellow;
    wordcellrange.Borders[WdBorderType.wdBorderRight].ColorIndex =
      Word.WdColorIndex.wdBlue;
    wordcellrange.Borders[Word.WdBorderType.wdBorderRight].LineWidth =
      Word.WdLineWidth.wdLineWidth025pt;
    

    Не составляет труда и выполнить заливку:

    wordcellrange.Shading.ForegroundPatternColor=
                        Word.WdColor.wdColorDarkYellow;
    wordcellrange.Shading.BackgroundPatternColorIndex=
     Word.WdColorIndex.wdGreen;
    

    И последнее, что может понадобиться - выравнивание, которое выполняется аналогично выравниванию текста для параграфа текста:

    wordcellrange.ParagraphFormat.Alignment=
      Word.WdParagraphAlignment.wdAlignParagraphCenter;
    


    В начало

    7.3. Объединение ячеек таблиц

    Параграф добавлен по просьбе назвавшего себя pasportbez1:

    Дата: 30.10.08 12:45 
    От кого: dm dm <pasportbez1@???????>     В адресную книгу:  В черный список: 
     
    Кому: wladm <wladm@narod.ru> 
     
    Тема: Хелп ! 
     
    Привет!, прошу прощение за беспокойство, я к тебе с просьбой - не мог бы 
    ты описать один момент на своем сайте в c# - когда открываешь ворд и 
    вставляешь туда таблицу - как можно объеденить ячейки ?
    
    Заранее пасибо !
    

    В примере использованы Reference:

    Microsoft.Office.Tools.Word со вкладки .Net
    Microsoft Word 11.0 Object Library со вкладки COM
    

    Текст программы практически полностью без того, что создает студия:

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Text;
    using System.Windows.Forms;
    using System.Collections;
    //Добавляем
    using Word = Microsoft.Office.Interop.Word;
    
    
    
    private Word.Application wordapp;
    
    private void button1_Click(object sender, EventArgs e)
    {
     try
     {
      //Создаем объект Word - равносильно запуску Word
       wordapp = new Word.Application();
       //Делаем его видимым
       wordapp.Visible = true;
       Object template = Type.Missing;
       Object newTemplate = false;
       Object documentType = Word.WdNewDocumentType.wdNewBlankDocument;
       Object visible = true;
       //Создаем документ 1
       Word.Document worddocument = wordapp.Documents.Add(
      ref template, ref newTemplate, ref documentType, ref visible);
       //Таблицу вставляем в начало документа
       Object start = 0;
       Object end = 0;
       Word.Range wordrange = worddocument.Range(ref start, ref end);
       Object defaultTableBehavior =
          Word.WdDefaultTableBehavior.wdWord9TableBehavior;
       Object autoFitBehavior = Word.WdAutoFitBehavior.wdAutoFitWindow;
       //Добавляем таблицу и получаем объект wordtable 
       Word.Table wordtable = worddocument.Tables.Add(wordrange, 5, 5,
                         ref defaultTableBehavior, ref autoFitBehavior);
    
       //Можно так (метод доминирует в ИНЕТЕ), но не рекомендую - не сможите 
       //объединить вертикально  две ячейки
    
       //object begCell = wordtable.Cell(1, 1).Range.Start;
       //object endCell =  wordtable.Cell(1, 2).Range.End;
       //Word.Range wordcellrange = worddocument.Range(ref begCell, ref endCell);
       //wordcellrange.Cells.Merge();
    
       //Рекомендую так, объединяет как угодно 
       //В столбец (вертикально) две ячейки
       object begCell = wordtable.Cell(1, 1).Range.Start;
       object endCell =  wordtable.Cell(2, 1).Range.End;
       Word.Range wordcellrange = worddocument.Range(ref begCell, ref endCell);
       wordcellrange.Select();
       wordapp.Selection.Cells.Merge();
    
       //В строку (горизонтально) две ячейки
       begCell = wordtable.Cell(3, 1).Range.Start;
       endCell = wordtable.Cell(3, 2).Range.End;
       wordcellrange = worddocument.Range(ref begCell, ref endCell);
       wordcellrange.Select();
       wordapp.Selection.Cells.Merge();
    
       //Квадратом
       begCell = wordtable.Cell(3, 3).Range.Start;
       endCell = wordtable.Cell(4, 5).Range.End;
       wordcellrange = worddocument.Range(ref begCell, ref endCell);
       wordcellrange.Select();
       wordapp.Selection.Cells.Merge();
      }
      catch (Exception ex)
      {
       Text = ex.Message;
      }
    }
    

    Результат:

    wordexce0309.gif

    Рис.10. Объединение ячеек


    В начало

    Параграф 8. Защита документа

    Материал прислан Андреем Ковалевым и отредактирован автором.

    Для защиты документа необходимо установить пароль. В качестве пароля используется любая переменная тира Object.

    Рассмотрим код:

    Object missing = Type.Missing;
    Object NoReset = true;
    Object pass = "andrey";
    worddocument.Protect(Word.WdProtectionType.wdAllowOnlyReading, ref NoReset, ref
     pass, ref missing, ref missing);
    

    Соответственно функция в Microsoft.Office.Interop.Word.dll, определена как:

    void Protect(WdProtectionType Type, 
                ref object NoReset, 
                ref object Password, 
                ref object UseIRM, 
                ref object EnforceStyleLock);
    

    Соответственно параметры:

    • WdProtectionType:

      • wdNoProtection - не применять защиту к документу;

      • wdAllowOnlyRevisions - только запись исправлений;

      • wdAllowOnlyComments - позволяет только добавлять коментарии к документу;

      • wdAllowOnlyFormFields - позволяет добавлять содержание через поля формы;

      • wdAllowOnlyReading - только чтение документа.

    • noReset - значение false, чтобы сбросить поля формы к значениям по умолчанию. Значение true, чтобы сохранить текущие значения полей формы, если документ защищен. Если Type не является wdAllowOnlyFormFields, аргумент NoReset игнорируется.

    • password - пароль.

    • useIRM - определяет, следует ли использовать механизм управления правами на доступ к данным (IRM) для защиты документа от изменений.

    • enforceStyleLock - определяет, были ли в защищенном документе принудительно реализованы ограничения форматирования.

    Приведенный выше код, соответственно, разрешает только чтение документа и позволяет сохранить текущие значения полей формы.

    Для снятия защиты используем:

    Object pass = ="andrey";
    worddocument.Unprotect(ref pass); 
    
    


    В начало

    Параграф 9. Диалоговые окна

    Материал прислан Павлом Матрениным и отредактирован автором.

    Многие действия в Word сопровождаются вызовом диалоговых окон (создание, открытие, сохранение и печать документа, изменение параметров шрифта, текста и т.д.).

    Допустим, необходимо предоставить пользователю возможность отправить документ на печать прямо из вашего приложения. Можно использовать функцю Document.PrintOut, но у нее "устрашающее" количество параметров, как и у большинства функций связи C# с COM объектами. Мы это видели в функциях, использованных выше, см., например, функцию SaveAs и другие.

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

    Перейдем к примеру вызова диалогового окна печати документа:

    Object time = 10000;
    wordapp.Dialogs[Word.WdWordDialog.wdDialogFilePrint].Show(ref time);
    

    Dialogs - это коллекция диалоговых окон Word (всего 296 элементов класса Microsoft.Office.Interop.Word.Dialog). Для того, что бы посмотреть все доступные диалоговые окна, кликните правой кнопкой мышки на WdWordDialog и выберите пункт меню "Go To Defination".

    Элементы доступны по своим именам и имеют понятные названия, например:

    • wdDialogFileNew - Новый документ;
    • wdDialogFileOpen - Открыть документ;
    • wdDialogFilePageSetup - Параметры страницы;
    • wdDialogFilePrint - Печать;
    • wdDialogFileSaveAs - Сохранить документ;
    • wdDialogFormatFont - Параметры шрифта.

    Определение функции Dialog.Show в Microsoft.Office.Interop.Word.dll:

    int Show(ref object TimeOut); 
    

    Параметр: "TimeOut" - время в миллисекундах, через которое окно будет закрыто автоматически. Практика показывет, что некоторые виды окон игнорируют это время и сами не закрываются. Это относится к сохранению, открытию, созданию нового документа... Окна для указания параметров "печати, параметров страницы, шрифта...." закрываются по истечении указанного времени.

    Значение, которое возвращает функция Show, зависит от вида окна и от того, как оно было закрыто. Если вышло время, или пользователь нажал "OK", или "Закрыть", то "-1", если "Отмена", то "0", если "По умолчанию", то "1". А вот если окно закрыто крестиком, то может быть "-1" или "-2", зависит от самого окна. Других значений в своих опытах я не встречал (П.Матренин).

    Обратите внимане на то, что попытка вызвать диалоговое окно, которое не может быть вызвано (например, сохранение, если пока не создано ни одного документа) приводит к возникновению исключительной ситуации.

    Заметим также, что при Object time = 0 диалоговое окно появляется на не установленное время, иначе, программа будет ожидать действий пользователя с диалоговым окном.


    В начало

    Параграф 10. Основы анализа документов Microsoft Word

    Материал прислан Сергеем Бабичевым, переведен на C# и отредактирован автором.

    Очень часто людям приходится заниматься так называемой “обезьяньей работой”, нудным и совершенно нетворческим делом. Например, форматировать документы по некоторому образцу или проверять ссылки в разных документах друг на друга, искать соответствие товаров в разных накладных и ведомостях…. При этом очень легко ошибиться, что-то пропустить и на все это уходит много времени и сил.

    Что бы автоматизировать труд и избавиться от лишней работы необходимо знать основы анализа и преобразования формы документов. В данном параграфе приводятся лишь некоторые возможности, предоставляемые OLE сервером Word, которые могут быть использованы при анализе и преобразования документов.

    За основу примеров взяты наработки автора сайта из этого раздела. Имена переменных соответствуют именам, используемым в данной главе.

    После написания кода запуска OLE сервера Word и открытия документа можно приступить к его анализу.

    Если нужно просмотреть весь документ по параграфам, то можно сделать это таким циклом:

    string s = string.Empty;
    try
    {
     for (int i = 1; i < worddocument.Paragraphs.Count; i++)
     {
      s= worddocument.Paragraphs[i].Range.Text;
      vTestText(s);   // Функция, которая будет обрабатывать текст абзаца
     }
    }
    catch (Exception ex)
    {
        Text = ex.Message;
    }
    

    В функции vTestText мы можем просто выполнить анализ текста, например, на поиск некоторых слов (наименований товара...).

    Если мы поместим абзац в переменную wordrange, объявленную как

    private Word.Range wordrange = null;
    

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

    try
    {
     for (int i = 1; i < worddocument.Paragraphs.Count; i++)
     {
      wordrange = worddocument.Paragraphs[i].Range;
      vTestRange(wordrange);
     }
    }
    catch (Exception ex)
    {
     Text = ex.Message;
    }
    

    Функция vTestRange определим как:

    private void vTestRange(Word.Range wordrg)
    {
    }
    

    Что можно сделать в данной функции.

    1. Выделить нужный абзац для дальнейших его преобразований или анализа: 

      wordrg.Select();
      
    2. Выбрать текст абзаца в некоторую строковую переменную:

      s=wordrg.Text;
      
    3. Определить номер страницы, на которой расположен абзац:

      object vobjN = wordrg.get_Information(Word.WdInformation.wdActiveEndPageNumber);
      Text = vobjN.ToString();
      

      Другая константа - wdActiveEndAdjustedPageNumber, позволяет определить номер листа документа, когда нумерация в нем начинается не с первого номера, то есть используется своя нумерацию страниц документа.

    4. Проверить на вхождение абзаца в таблицу:

      • так

        if (wordrg.Tables.Count > 0)
        {
         Text = wordrg.Text + " находится в таблице";
        }
        
      • или так

        object vobjTable = wordrg.get_Information(Word.WdInformation.wdWithInTable);           
        Text=vobjTable.ToString();
        if (Text != "False")
        {
         Text = wordrg.Text + " находится в таблице";
        }
        
    5. Если абзац в таблице, то можно узнать номер строки и столбца таблицы:

      vobjTable = wordrg.get_Information(Word.WdInformation.wdStartOfRangeRowNumber);
      Text ="Строка: "+ vobjTable.ToString();
      vobjTable = wordrg.get_Information(Word.WdInformation.wdStartOfRangeColumnNumber);
      Text +=" Столбец: "+ vobjTable.ToString();
      

      Также этот код позволяет определить число строк и столбцов в таблице (методом перебора по максимальному числу номера строки и столбца).

    6. Узнать или изменить форматирование абзаца:

      • узнать жирный (наклонный, подчеркнутый...) или нет шрифт:

        s=wordrg.FormattedText.Bold.ToString()
        

        "-1" - жирный, "0" - нет;

      • установит жирный или другой тип шрифта;

        wordrg.FormattedText.Bold = -1;
        
    7. Узнать или изменить параметры шрифта:

      • узнать:

         Word.Font mf = wordrg.FormattedText.Font;
         string s = mf.Name+"  "+mf.Size.ToString();
         Text = s;
        
      • изменить:

        wordrg.Font.Size = 24;
        wordrg.Font.Bold = 1;
        wordrg.Font.Color = Word.WdColor.wdColorGray30; 
        
    8. Узнать число символов в параграфе (может быть использовано для последующего поиска символов или поиска и замены, форматирования...):

      Word.Characters wch = wordrg.FormattedText.Characters;
      int n= wch.Count;
      wch[10].Font.Size =25;//Изменить шрифт отдельного символа параграфа
      if (n > 10) n = 10;
      //Изменить шрифт 10 первых символов параграфа
      for (int i = 0; i < n; i++)
      {
       wch[i+1].Font.Size = 25;
      }
      
    9. Использовать объект Case, который предназначен для преобразования текста параграфов, но может быть использован и для анализа. Объект имеет множество свойств (даже для изменения текстов написанного иероглифами). Для нас могут быть интересны значения: wdLowerCase; wdUpperCase; wdNextCase; wdToggleCase; wdTitleWord; wdTitleSentence. Эти свойства позволяют соответственно перевести текст параграфа в нижний, верхний регистры, менять регистр, преобразовать первую букву каждого слова или предложения в верхний регистр.

      Соответственно:

      • для преобразования может быть использован код: F:\My_Site\C_Sharp\comword.html

        wordrg.FormattedText.Case = Word.WdCharacterCase.wdUpperCase;
        
      • для анализа может быть использован код:

        if (wordrg.FormattedText.Case == Word.WdCharacterCase.wdUpperCase)
        {
         //действие
        }
        //если слова, написаны в смешанном регистре, то
        //FormattedText.Case имеет значение wdToggleCase
        
    10. Использовать объект PageSetup для анализа и форматирования документа:

      Word.PageSetup wps = wordrg.FormattedText.PageSetup;
      if (wps.LeftMargin < 100)
      {
       wps.LeftMargin = 100;
      }
      

      Другие интересные свойства PageSetup, которые могут быть использованы для анализа и форматирования VerticalAlignment, RightMargin, TopMargin, LinesPage(строк на странице).

      
      
    11. Использовать объект Fields для анализа документа и поиска в документе:

      Объявим объект Fields как:

      Word.Fields wordfields; 
      wordfields = wordrg.Fields;
      
      • Если абзац содержит поля, например гиперссылки или принадлежит оглавлению, то его свойство Count больше 0.

        if (wordfields.Count > 1)
        {
        }
        
      • Определение принадлежности к оглавлению:

        В общем плане, структура оглавления примерно такая:

        • Первый и последний абзац его содержат в свойстве Fields ссылки на все остальные абзацы оглавления.

        • В первом поле содержится текст «TOC»

        • Остальные поля выглядят примерно так: HYPERLINK \\l \"_Toc295237884\ или так: PAGEREF _Toc295237884 \\h (цифры скорее всего означают смещение в байтах).

        Встречаются документы, в которых абзац, не принадлежащий оглавлению содержит в себе поле с текстом "_Toc" (загадка). Поэтому проверять на вхождение абзаца в оглавление лучше по слову "PAGEREF". Кроме того, пустой абзац после оглавления, содержащий всего лишь символ перехода на новую строку (\r), также может содержать "PAGEREF". И, для того чтобы отличить текст оглавления от его завершения, может понадобиться проверка текста абзаца на наличие только "\r".

        Word.Fields wordfields;
        wordfields = wordrg.Fields;
        string s = string.Empty;            
        if (wordfields.Count > 1)
        {
         for (int a = 0; a < wordfields.Count; a++)
         {
          s = wordfields[a + 1].Code.Text;
          if (s.ToUpper().Contains("PAGEREF") && wordrg.Text.Trim().Length > 0)
          {
            Text = " Абзац, содержащий " + wordrg.Text+" принадлежит к оглавлению";
          }  
         }
        }
        
      • Определение наличия гиперссылки в абзаце.

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

        Word.Fields wordfields;
        wordfields = wordrg.Fields;
        string s = string.Empty;
        bool f = false;
        if (wordfields.Count > 0)
        {
         for (int a = 0; a < wordfields.Count; a++)
         {
          s = wordfields[a + 1].Code.Text;
          if (s.ToUpper().Contains("PAGEREF") && wordrg.Text.Trim().Length > 0)
          {
           f = true; ;
          }
         }
         for (int a = 0; a < wordfields.Count; a++)
         {
          s = wordfields[a + 1].Code.Text;
          if (s.ToUpper().Contains("HYPERLINK") && !f && wordrg.Text.Trim().Length > 0)
          {
           Text = " Абзац, содержащий " + wordrg.Text + " содержит гиперссылку";
          }
         }
        }
        
      • Определение принадлежности абзаца к списку.

        if ((int)wordrg.ListFormat.ListType > 0 && (int)wordrg.ListFormat.ListType <= 6)
        {
         Text = "Абзац принадлежит к списку типа " + wordrg.ListFormat.ListType.ToString();
         Text = "";
        }
        //Свойство Text для абзаца из списка будет иметь одно из значений, перечисленных ниже:
        //Абзац принадлежит к списку типа  wdListSimpleNumbering
        

        Возможные значения:

        • wdListNoNumbering = 0,

        • wdListListNumOnly = 1,

        • wdListBullet = 2,

        • wdListSimpleNumbering = 3,

        • wdListOutlineNumbering = 4,

        • wdListMixedNumbering = 5,

        • wdListPictureBullet = 6.

        Для определения принадлежности абзаца к списку можно использовать свойство ListString. Правда это потребует знания кодов типов маркеров и нумерации списка, так как не все признаки линии в списках (некоторые черточки, например) приводятся к читаемым строковым символам, и кроме того, пользователь может назначить свои маркеры и нумерацию. Поэтому этот способ не всегда оправдан, разве что, для поиска в документе конкретных типов маркеров или конкретной нумерации.

        if ((int)wordrg.ListFormat.ListType > 0 && (int)wordrg.ListFormat.ListType <= 6)
        {
         string s = wordrg.FormattedText.ListFormat.ListString.Trim();
         if (!string.IsNullOrEmpty(s))
         {
          s=s.Trim();
          if (s.Contains(".")) s = ".";
          char vch = Convert.ToChar(s);
          UInt16 vui16 = Convert.ToUInt16(vch);
          if (vui16 == 0xF02D)
          {
            Text = wordrg.Text + " - Абзац принадлежит к списку типа " + wordrg.ListFormat.ListType.ToString();
          }
         }
        }
        //Текст в заголовке формы
        //"текст абзаца" - Абзац принадлежит к списку типа wdListOutlineNumbering
        

        Некоторые возможные значения кодов маркеров и нумераций:

        • wdListBullet = 0xF0B7,0xF0A7, 0x6А, 0xF076, F0D8,F0FC...;

        • wdListSimpleNumbering = 0x2E, 0x29...

        • wdListPictureBullet = 0xF0B7...

    В заключение параграфа надо сказать, что формат документа Word не очень непростой и содержит огромное количество полей и свойств. Назначение многих из них непонятны, я думаю, даже программистам Microsoft (Сергеей Бабичев).


    В начало

    Параграф 11. Некоторые другие возможности по работе с Word

    Из приложения, управляя сервером Word, можно делать практически все, что и из автономно запущенного Word. Однако, во всех этих, потрясающих объемом доступных действий и возможностей, обычно нет необходимости. Здесь приведены лишь несколько возможностей, которые помимо приведенного выше материала, когда либо потребовались автору в его практической работе.

    Из приложения можно:

    • Сменить ориентацию листа и установить поля.

      Object start=Type.Missing;
      Object end=Type.Missing;
      Word.Range wordrange=worddocument.Range(ref start,ref end);
      wordrange.PageSetup.Orientation=Word.WdOrientation.wdOrientLandscape;
      wordrange.PageSetup.LeftMargin=wordapp.CentimetersToPoints((float)2.5);
      

      Аналогично установить все другие параметры, доступные из меню Файл / Параметры страницы, а именно: Orientation, TopMargin, BottomMargin, LeftMargin, RightMargin, Gutter, HeaderDistance, FooterDistance, PageWidth, PageHeight, FirstPageTray, OtherPagesTray, SectionStart, OddAndEvenPagesHeaderFooter, DifferentFirstPageHeaderFooter, VerticalAlignment, SuppressEndnotes, MirrorMargins, TwoPagesOnOne, BookFoldPrinting, BookFoldRevPrinting, BookFoldPrintingSheets, GutterPos.

    • Скопировать любой документ или его выделенный диапазон (объект Ramge) в буфер обмена (например диаграмму Excel) или вставить в документ что-то из буфера обмена:

      wordrange.Paste();
      wordrange.Copy();
      
    • Изменить масштаб документа:

      wordapp.ActiveWindow.ActivePane.View.Zoom.Percentage=75;
      
    • Изменить размер отображения окна:

      //Значение Word.WdWindowState констант: 
      //wdWindowStateMaximize, wdWindowStateNormal, wdWindowStateMinimize
      wordapp.WindowState=Word.WdWindowState.wdWindowStateMaximize;
      
    • Отменить любое количество выполненных из приложения действий:

      object back = 2;
      worddocument.Undo(ref back);
      
    • Управлять параметрами окна Word, и прочитать установочные данные:

      //Отобразить - показать статус Бар 
      //(аналогично, для панелей инструментов): 
      //bool bln = (wordapp.DisplayStatusBar); 
      wordapp.DisplayStatusBar = !bln; 
      //Узнать директория Word:
      MessageBox.Show(wordapp.Path);
      //Имя пользователя
      MessageBox.Show(wordapp.UserName); 
      
    • Поиск в документе:

      Документ открыт и есть объект документа:

      //Посмотреть весь документ
      Object start = 0;
      Object end = worddocument.Characters.Count;
      Word.Range wordrange = worddocument.Range(ref start, ref end);
      wordrange.TextRetrievalMode.IncludeHiddenText = false;
      wordrange.TextRetrievalMode.IncludeFieldCodes = false;
      MessageBox.Show(wordrange.Text);
      //Посмотреть фразу
      string sText = "Кабы я была царица";
      int beginphrase = 0;
      beginphrase = wordrange.Text.IndexOf(sText);
      start = beginphrase;
      end = beginphrase + sText.Length;
      wordrange =  worddocument.Range(ref start, ref end);
      MessageBox.Show(wordrange.Text);
      textBox1.Text = wordrange.Text + " Найденный текст начинается с позиции: " 
      + Convert.ToString(beginphrase);
      
    • Вставка картинок в приложение (решение прислала Оксанчик):

      wordapp.Selection.InlineShapes.AddPicture(@"C:\3.jpg", ref oMissing, ref oMissing, ref oMissing); 
      
    • Вставка разрава - на другой лист

      //Сдвигаемся вниз в конец документа
      object unit;
      object extend;
      unit = Word.WdUnits.wdStory;
      extend = Word.WdMovementType.wdMove;
      wordapp.Selection.EndKey(ref unit, ref extend);
      object oType;
      oType = Word.WdBreakType.wdSectionBreakNextPage;
      //И на новый лист
      wordapp.Selection.InsertBreak(ref oType);
      

      Нумерация листов в Word

      public void vInsertNumberPages(int viWhere, bool bPageFirst)
      {
       object alignment = Word.WdPageNumberAlignment.wdAlignPageNumberCenter; 
       object bFirstPage = bPageFirst;
       object bF = true;            
       // создаём коллонтитулы            
       worddocument.ActiveWindow.ActivePane.View.SeekView = Word.WdSeekView.wdSeekCurrentPageHeader; 
       switch (viWhere)
       {                
        case 1:
            alignment = Word.WdPageNumberAlignment.wdAlignPageNumberRight;      
            break;
        case 2:
            alignment = Word.WdPageNumberAlignment.wdAlignPageNumberLeft;      
            break;
       }
       wordapp.Selection.HeaderFooter.PageNumbers.Add(ref   alignment, ref   bFirstPage);
      }
      


    В начало

    Заключение. О богатстве возможностей

    Еще раз повторим, сказанное в Главе 2, богатства возможностей по управлению запущенным приложением потрясающе. Практически, все, что можно сделать в автономно запущенном приложении доступно и из приложения на C#. Каждый может достаточно легко выполнить то или иное действия из приложения, если создаст макрос для этого действия, а, затем, "переведет" код VBA в коды C#.

    И, в тоже время, по мнению автора, для начального этапа практической работы по формированию документов из приложения, изложенного материала вполне достаточно. Но, несмотря на это, раздел будет пополняться по мере возникновения какой либо проблемы в практической работе и ее разрешении. Если у Вас есть интересные находки - присылайте - с указанием авторства они будут включены в данный материал.

    Литература


    Молчанов Владислав 31.01.2005г.

    Адаптировано к VS 2005/2008 17.10.2007г.

    Перепечатка статьи без разрешения автора не допускается.

    Еcли Вы пришли с поискового сервера - посетите мою главную страничку

    На главной странице Вы найдете программы комплекса Veles - программы для автолюбителей, программы из раздела графика - программы для работы с фото, сделанными цифровым фотоаппаратом, программу Bricks - игрушку для детей и взрослых, программу записную книжку, программу TellMe - говорящий Русско-Английский разговорник - программу для тех, кто собирается погостить за бугром или повысить свои знания в английском, теоретический материал по программированию в среде Borland C++ Builder, C# (Windows приложения и ASP.Net Web сайты).

    logo.gif

    В начало страницы

    К началу раздела

    К началу книги

    На главную страницу


  • Сайт управляется системой uCoz