Основы офисного программирования и язык VBA

Начнем с объектов Office 2000

Разбить на страницы
Показывать лекцию целиком

Программный код большинства примеров данной лекции можно найти в проектах, доступных для просмотра: BookOne, BookThree, BookFive, Dex1, DocFive, DocThree.

VBA и объекты. Обзор

В этой книге основное внимание мы хотим уделить самому языку VBA - его ядру, средствам, определяющим этот язык, как обычный язык программирования. Но заранее можно предсказать, что "столкновения" или лучше сказать встречи с объектами нам не избежать. Все-таки, сутью VBA является его возможность непосредственной работы с объектами. Поэтому эту лекцию мы решили посвятить первому знакомству с объектами. Подробное их рассмотрение будет предметом следующей книги.

Office - это среда, в которой многие задачи можно решать без всякого программирования. Office 2000 - это среда, в которой класс таких задач существенно расширился. Но для программиста ценность офисной среды состоит в том, что все задачи, решение которых может быть получено "руками", можно получить и программно. И все, что нельзя сделать руками, можно сделать программно. Для программирования используется язык VBA (Visual Basic for Applications), представляющий расширение ядра языка VB (Visual Basic) объектами, определяющими приложения Office 2000.

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

  • В работе участвуют специалисты в проблемной области и программисты. Целью работы является создание системы "живых" документов офиса или предприятия. Работа строится на мощной основе, которую составляют документы, предоставляемые средой Office 2000. Документами могут быть бланки, отчеты, справки, базы данных, запросы к ним, графики, диаграммы. Документы мы называем живыми, поскольку в процессе работы конечных пользователей (специалистов) они могут изменяться. Эти изменения являются результатом выполнения различных функций над данными, размещенными в документах.
  • Библиотека объектов Office 2000 представляет собой каркас документов (чуть позже мы определим более точно этот термин). Открывая впервые одно из приложений Office 2000, например Word, специалист получает готовый каркас некоторого документа, - для Word это документ, в котором основным типом данных будут тексты. Затем специалист берется за дело и наполняет этот каркас плотью и кровью, создавая уже реальный документ, входящий в общую систему. Однако, как бы ни увеличивались стандартные возможности среды, всегда для оживления документа чего-нибудь да не хватает, (вспомните, мечту о дефиците одного из героев Райкина). И тогда приходит время программиста.
  • В процессе создания "живых" документов программист будет работать на VBA, едином языке программирования, объединяющем мир объектов среды Office 2000. VBA представляет мощный, универсальный язык программирования и на нем можно делать все, или почти все, что и на любом другом языке программирования. Но главное его достоинство состоит в том, что в нем определены и доступны для программиста все объекты Office 2000. Это значит, что доступны все документы, все их части, и части этих частей, вплоть до символа, рисунка, ячейки. Это и позволяет программисту легко проводить настройку системы документов с учетом их специфики. (В английском языке для этой деятельности есть хороший термин - customization, но, может быть, и термин "настройка" не хуже).
  • Ранее уже говорилось, о том, что такой стиль работы становится популярным. Язык VBA является теперь отчуждаемым от среды Office 2000, он может быть встроен в любую другую среду. Реально этот процесс уже идет, мы приводили пример с программными продуктами фирмы Corel, но есть и большое число других подобных примеров.

    Библиотека объектов Office 2000 - каркас приложений

    В тех книгах, которые мы написали последнее время по Visual C++ и по Офисному программированию, большая часть достаточно солидного введения посвящалась основам объектно-ориентированного программирования. Мы полагаем, что каждый программист должен владеть этим аппаратом, поскольку без четкого осознания таких понятий, как класс, интерфейс класса, полиморфизм, наследование, встраивание, невозможно проектирование и разработка сколь либо серьезной системы документов. В этой книге мы не будем останавливаться на этих понятиях, полагая, что читатели с ними знакомы, если же нет, то можно порекомендовать обратиться к нашим книгам по Visual C++ и Офисному программированию, или к любым другим, где эти вопросы хорошо изложены.

    Но на одном термине стоит все-таки остановиться подробнее. Речь пойдет о понимании совокупности библиотек классов, как каркаса приложений (каркаса документов). Когда программист вводит собственный класс объектов, то чаще всего он рассматривает его, как специфический тип данных, расширяющий возможности типов данных, встроенных в язык. Первые библиотеки классов, предоставляемые системой программисту, по существу, представляли расширенный набор типов данных. Но затем стало понятным, что объектный подход может быть полезным и при построении самого приложения. Само приложение стало рассматриваться, как совокупность объектов со своими свойствами, методами и событиями. Более того, стало ясно, что можно строить приложения различной архитектуры и стандартных скелетов приложений не так уже и много. При работе в среде Visual C++ , например, классической является архитектура Документ - Облик (Document -View).

    В современных программных средах большую часть классов, входящих в библиотеку (совокупность библиотек), составляют классы, предназначенные для построения самого приложения, его основы или каркаса. В соответствии с этим такие библиотеки называются каркасом приложений (FrameWork Applications). Такую роль играют библиотеки Visual C++, Delphi и других программных сред.

    Как же обстоит дело в Office 2000? Для программиста Office 2000 - это ничто иное, как обычная совокупность библиотек классов. И так же, как и для других программных сред, их классы представляют собой каркас приложений, или, что может быть точнее с содержательной точки зрения, - каркас документов.

    Дело в том, что изменились цели программиста, работающего в среде Office 2000. Ранее целью программиста было создание приложения, понимаемого как программа, программный проект. Теперь программист является одним из участников (возможно единственным) создания системы документов. Документ, а не программа, становится целью разработки. Программный проект - это лишь часть документа. В Office 2000 программный проект неразрывно связан с документом, хранится, как часть документа, и не может существовать независимо от него. Отсюда становится понятным, что и библиотека классов Office 2000 содержит каркасы основных документов - текстовых документов, документов, основу которых составляют электронные таблицы, презентации, базы данных. Всякий раз, когда создается новый документ, его каркас составляют объекты библиотек, отобранных для построения этого конкретного каркаса документа.

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

    Встраивание вместо наследования

    Обычно, классы, входящие в библиотеку, связаны между собой. Типично, на классах вводится отношение наследования, так что в иерархически связанном семействе классов есть родительские классы и классы - потомки. Наследование - мощный и естественный механизм порождения новых классов. Прародитель семейства может задавать некоторые общие, наиболее фундаментальные свойства и поведение объектов этого семейства, а его многочисленные потомки задают то или иное специализированное поведение. Кроме того, отметим, что наследование позволяет модифицировать поведение объектов - потомков, не меняя поведения объектов исходного родительского класса. Это важный принцип - "не разрушай то, что создано ранее". Ценность такого подхода, в частности, состоит и в том, что каркас конкретного приложения составляют классы - потомки, чьи родители находятся в библиотеке. Поэтому можно добавлять новые свойства, изменять и добавлять новое поведение у приложения, - все это никак не сказывается на родительских классах, хранящихся в библиотеке.

    Наследование, конечно же, не единственно возможное отношение между классами. Программистам хорошо известно встраивание - еще один способ построения нового класса, использующий ранее созданные классы. Пусть построен класс А, тогда при определении нового класса В его элементами - переменными (свойствами класса В ) могут быть объекты класса А. В этом случае говорят, что объекты класса А встроены (вложены) в класс В. Встраивание, как и наследование, - транзитивное отношение. Реально это означает, что возможна сколь угодно высокая степень вложенности объектов. Следует отличать непосредственную вложенность от вложенности уровня n. Так, в новый класс С можно встроить объект класса В, и он будет непосредственно вложен в класс С, а объект класса А, встроенный в объект В, будет иметь уровень вложенности 2 по отношению к классу С.

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

    Class Mother
    {
    	'Раздел атрибутов
    	Chromosome XX;
    'Другие объявления свойств и методов
    ....
    }
    Class Father
    {
    	'Раздел атрибутов
    	Chromosome XY;
    'Другие объявления свойств и методов
    ....
    }

    В классы Mother и Father встроены объекты XX и XY ранее определенного класса Chromosome. Используя множественное наследование, можно создать новый класс, наследующий свойства и поведение его родителей:

    Class Child : Parents Mother, Father
    {
    	'Наследует свойства XX, XY и другие свойства и методы своих родителей
    	'Раздел атрибутов
    	String 	NewProperty;
    	'Другие новые свойства и методы
    }

    Рассмотрим теперь создание класса, основанное на встраивании объектов:

    Class MyChild
    {
    	'Раздел атрибутов
    	Father	F;
    	Mother	M;
    	String	NewProperty;
    	'Другие новые свойства и методы
    }

    Вот объявление объектов этих классов:

    Child 	Son;
    MyChild	Daughter;

    Объекты Son и Daughter обладают одинаковыми свойствами и поведением. И в этом случае мы будем говорить, что классы Child и MyChild подобны. Есть некоторая синтаксическая разница - у объекта Son свойства XX и XY доступны непосредственно, а у объекта Daughter они доступны через вложенные объекты F и M, так что в первом случае мы пишем Son.XX и Son.XY, а во втором - Daughter.F.XY и Daughter.M.XX.

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

    Если происходит переопределение родительских методов в производном классе, то в общем случае, используя встраивание, нельзя построить класс, подобный наследуемому. В нашем примере с классами Child и MyChild встраивание используется при построении класса MyChild как альтернатива наследованию. С другой стороны, в этих классах применяется, и "обычное" встраивание. Заметьте: свойства XX и XY в классах Child и MyChild - это встроенные объекты ранее определенного класса Chromosome. Так что этим примером мы демонстрируем обе ипостаси встраивания.

    Мы так подробно остановились на встраивании по одной простой причине: этот механизм лежит в основе объектной модели в Office 97 и Office 2000. Здесь нет наследования в истинном смысле этого слова, и хотя этот термин иногда и используется, но фактически всегда речь идет лишь о встраивании. Все приложения Office 2000 с объектной точки зрения построены одинаково. Всегда существует задающий приложение корневой объект Application ( Word.Application, Excel.Application и т. д.), в который встроены все остальные объекты данного приложения.

    Когда в объект Application вложен объект X, говорят, что у объекта Application есть свойство X, и запись Application.X означает обращение к объекту X. Сам объект X может быть не менее сложен: в него могут быть встроены другие объекты, например объект Y, а в него в свою очередь - объект Z. Эта цепочка вложенности может быть продолжена. Для приложений Office 2000 типична ситуация, при которой нужно указать 6-7 уровней вложенности, чтобы добраться до объекта, свойство или метод которого будет использовано. Вложенный объект, который является свойством объекта, его содержащего, называют иногда участником (accessor).

    Длинные цепочки, возникающие при именовании объектов, являлись бы большим недостатком, если бы их пришлось выписывать вручную. Но вот пример того, как недостатки можно обращать в достоинства. Частью, используемой в Office 2000 всюду, где можно, технологии интеллектуальной поддержки (intellisense) является поддержка автоматического выписывания длинных имен. Как только после имени объекта ставится точка, автоматически раскрывается список с перечислением всех свойств этого объекта, так что остается только выбрать имя из списка, поставить точку и продолжить этот процесс. Если, поставив точку, Вы не видите списка, то это значит, что-то сделано неправильно, например, не задан класс объекта в операторе объявления или неверно понимается его структура, в любом случае это сигнал, заставляющий задуматься.

    Подводя итог, отметим, что для программиста большинство библиотек Office 2000 задают совокупность "толстых" объектов - объектов Application. В каждый такой корневой объект вложены другие объекты, устроенные не менее сложно. С методами, свойствами и событиями, происходящими в мире этих объектов, и работает программист.

    В заключение взгляните, как я представляю себе "толстый" объект Application.

    (рис 1.1) Вложенность объектов

    Построение каркаса документа

    Мы уже сказали, что совокупность библиотек классов Office 2000 представляет каркас документов, которые могут порождаться в этой программной среде. Давайте же рассмотрим, как создается каркас одного документа. Обычно, это тривиальная операция, выполняемая почти автоматически. В свое время, рассматривая программирование в среде Office 97, мы не считали необходимым введения самого термина "каркас документа". В Office 2000 возросли возможности создания разнообразных каркасов, потому стоит ввести и сам термин и обратить на это особое внимание.

    Итак, всякий раз, когда открывается новый документ в одном из приложений Office 2000, например Word, Excel или Power Point , автоматически создается каркас этого документа. Это означает, что из всей совокупности библиотек выбираются те библиотеки, которые и будут составлять каркас этого документа. И это означает, что все объекты, классы которых определены в этих библиотеках, будут доступны в данном документе.

    Какие же библиотеки входят в каркас документа по умолчанию? Определяющую роль играет то, в каком приложении Вы создаете документ. В каркас всегда входит библиотека, задающая это приложение, - Word 9, Excel 9 или тот же Power Point 9. В состав этой библиотеки входит корневой объект Application ( Word9.Application, Excel9.Application и т.д.). Этот корневой объект и определяет основную структуру документа. Но помимо этой библиотеки в каркас всегда входят и другие библиотеки. Взгляните на каркас по умолчанию документа Word:

    (рис 1.2) Каркас по умолчанию документа Word

    Как можно видеть, в каркас входят кроме библиотеки Word еще три библиотеки и два проекта:

  • Word - библиотека, задающая основу документов Word. Здесь хранится корневой объект Application и все классы объектов, вложенных в корневой объект.
  • Office - библиотека объектов, общих для всех приложений Office 2000. Здесь находятся классы, задающие Помощника (объект Assistant и все классы, связанные с ним). Здесь же находятся классы, определяющие инструментальные панели - CommandBar и классы других общих объектов. В частности, появился новый объект, которого не было в предыдущей версии - Мастер Ответов (Answer Wizard) и его файлы.
  • Stdole - библиотека классов, позволяющая работать с OLE - объектами и реализовать Автоматизацию.
  • VBA - библиотека классов, связанных с языком VBA. Здесь хранятся все стандартные функции, встроенные в язык, и многое другое.
  • Project - проект по умолчанию, связанный с документом. Классы, которые могут программистом создаваться в этом проекте, методы, свойства, - все это доступно для просмотра, так же, как и объекты классов, встроенных в стандартные библиотеки.
  • Normal - проект, доступный для всех документов Word. Здесь могут храниться функции и классы, используемые всеми документами.
  • Состав каркаса для документов, открываемых в Excel или Power Point, почти такой же. Естественно, библиотека Word заменяется библиотекой соответствующего приложения. Кроме того, отсутствует проект Normal, характерный только для документов Word.

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

    А теперь о том, как это делается. Прежде всего, заметим, что расширение каркаса делается руками, а не программно. Для того чтобы добавить в документ новые возможности, необходимо вначале войти в режим редактора программного проекта, для чего достаточно из меню Tools | Macro выбрать пункт Visual Basic Editor или нажать комбинацию клавиш Alt + F11. Затем уже в Редакторе из меню Tools следует выбрать пункт References и в появившемся списке всех возможных библиотек, включить те, которые отвечают Вашим потребностям. На рис. 1.3 показан процесс подключения к документу Word новых библиотек.

    (рис 1.3) Расширение возможностей каркаса документа

    В частности, мы подключили библиотеки объектов трех приложений - Outlook, Access и Excel, библиотеку с WEB - компонентами, Мастер этих компонент и элемент управления для работы в Internet. В результате каркас документа существенно обновился, и наш документ теперь обладает потенциально большими возможностями, чем документ, создаваемый по умолчанию. В этом документе можно организовать совместную работу четырех приложений Office 2000, работать с WEB - компонентами и использовать возможности встроенного элемента управления при работе над документом в Internet. Конечно, каркас обеспечивает только потенциальную возможность, чтобы все заработало, нужно многое сделать, наполняя каркас плотью. Например, необходимо описать и создать соответствующие объекты Application для каждого из совместно работающих приложений, прежде чем начать с ними работать.

    На рис. 1.3 можно увидеть лишь небольшую часть всей совокупности библиотек (их несколько десятков), доступных в Office 2000. Профессионалу знать их, конечно, совершенно необходимо. Но знакомство с ними, хотя бы шапочное, выходит за пределы этой книги, посвященной VBA . О них и об объектах, в них хранящихся, пойдет разговор в других книгах, связанных общей темой офисного программирования в среде Office 2000.

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

    (рис 1.4) Окно просмотра объектов каркаса документа

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

    Библиотека объектов Office 2000 и Object Browser

    Мы уже говорили, что Office 2000, так же как и Office 97, задается совокупностью библиотек классов. Каждому приложению соответствует своя библиотека классов объектов. Кроме того, есть библиотеки с общими для всех приложений классами объектов. Библиотеки классов, задающих приложения, устроены одинаково. Есть корневой класс (корневой объект) Application (Excel, Word и т.д.). Это "толстый объект", как матрешка. В него вложено большое число объектов, эти объекты задают свойства корневого объекта и являются так называемыми свойствами - участниками. Помимо этого корневой объект имеет терминальные свойства, методы и события. Каждый вложенный объект устроен аналогично - он тоже "толстый", может быть более толстый, чем корневой.

    Сложность самой системы и большое количество составляющих ее объектов не позволяют описать все эти объекты в книгах наподобие этой. Необходимо также обращаться за справками к электронной документации. Справочная система по объектам в Office 97 была сделана, на наш взгляд, совсем неплохо, в Office 2000 она только улучшена. У Редактора VBE (Visual Basic Editor) есть инструментальное средство Object Browser (Окно просмотра объектов или, как теперь принято говорить, браузер объектов). Он позволяет просмотреть объекты, которые могут быть использованы в документе, увидеть их структуру - свойства, методы, события, получить справку и (или) пример использования.

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

    В браузере можно выбрать одну из библиотек каркаса документа, просмотреть ее структуру, для каждого класса объектов просмотреть его свойства, методы и события и тут же получить справку по каждому элементу. Вызывается Object Browser из редактора VBE выбором из меню пунктов View | Object Browser. А можно и быстрее: напомним, редактор вызывается нажатием клавиш Alt +F11, а Object Browser - F2.

    Взгляните еще раз на рис. 1.2 и рис. 1.4 , где показан Object Browser. В левом верхнем углу окна просмотра объектов расположен раскрывающийся комбинированный список Project/Library, содержащий имена доступных проектов и библиотек. В окне Classes отображается структура выбранного из списка класса или проекта - совокупность встроенных объектов. Выбрав один из объектов, в соседнем окне Members Вы увидите элементы этого объекта (свойства, методы, события). Каждый элемент - библиотека, класс, проект, свойство, метод, событие, свойство типа перечисление - сопровождается соответствующим значком. Щелкнув кнопку "справка" (со значком "?"), Вы получите быструю справку по выбранному элементу.

    Крайне полезное нововведение, сделанное в Office 2000, состоит в том, что в открывшемся окне справки можно щелкнуть кнопочку печати, позволяющее тут же напечатать справку. Более важно, что по другой кнопочке можно перейти в окно поиска информации по индексу, по оглавлению и в диалоге с Мастером Ответов (Answer Wizard). Единственный недостаток, справка и книги документации не согласованы, как это сделано в среде Visual C++, так что, найдя справку, вы не можете перейти в книгу документации, из которой эта справка взята, и просмотреть связный контекст. Так что есть еще место для совершенства справочной системы.

    Следует заметить, что в Office 2000 справку выдает Мастер ответов, обладающий новыми возможностями. Его можно настроить так, что он будет выдавать справки и по объектам, спроектированным программистом.

    Просматривать все объекты в поисках нужного - занятие довольно утомительное, поэтому в Object Browser имеются инструменты поиска. Ниже окна Project/Library расположен еще один комбинированный список, где нужно задать имя элемента поиска, а затем щелкнуть рядом расположенную кнопку поиска. При необходимости поиск можно осуществлять в одной из библиотек или во всех библиотеках (All libraries). Результаты поиска отображаются в специальном окне Search Results. На рис. 1.5 показаны результаты поиска слова Data в одной из библиотек.

    (рис 1.5) Окно с результатами поиска

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

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

    Объекты Application

    Всех объектов в Office 2000 не перечесть, но знать главные - обязательно. Давайте начнем знакомство с корней - объектов Application. Заодно посмотрим, что нового появилось в структуре этих объектов в сравнении с предыдущей версией. Чтобы облегчить и систематизировать нашу работу, мы по отдельности рассмотрим свойства - участники, терминальные свойства, методы и события этих объектов.

    Свойства-участники

    Свойства, представляющие вложенные объекты, называют свойствами-участниками. Если X является свойством - участником объекта Application, то обращение к свойству X возвращает ссылку на объект X. Обращение Application.X.Y.Z, где X, Y и Z - свойства-участники, позволяет добраться до объекта Z, находящегося на третьем уровне вложенности. Обычно цепочка именования начинается спецификатором (объектом) Application, но иногда его можно опустить. Некоторые свойства и методы объекта Application относятся к глобальным. Для них спецификатор Application разрешается опускать, непосредственно именуя глобальный элемент. Вот пример нескольких обращений к элементам объекта Application:

    Application.ActiveDocument ' Можно короче: ActiveDocument
    Application.ActiveWorkbook.ActiveSheet.Range("A1") = "Hi"' Можно так:
    ActiveSheet.Range ("A2") = "By-By"	' Можно и так:
    Range("A3") = "I'm glad to see you"  'Можно даже так!
    Application.Quit 'Только так! Quit не является глобальным методом.

    Познакомимся на верхнем уровне со структурой приложений и посмотрим, как она изменилась при переходе от Office 97 к Office 2000. На рис. 1.6 , рис. 1.7 , рис. 1.8 и рис. 1.9 показано, как выглядели объекты Application четырех основных приложений в Office 97. Что можно отметить, анализируя эту структуру:

  • Среди объектов, вложенных в Application, есть основные, задающие специфику приложения, - это документы Word (коллекция объектов Document ), рабочие книги Excel (коллекция объектов WorkBook ), презентации PowerPoint (коллекция объектов Presentation ), отчеты Access (коллекция объектов Report ). Позже мы познакомимся с ними подробнее, сейчас же отметим только, что каждый из них организован не менее сложно, чем их родитель - объект Application. Кроме основных объектов есть и вспомогательные объекты, специфичные для данного приложения. Например, у приложения Word это коллекции CustomDictionaries, Languages - коллекции пользовательских словарей и языков, используемых в документах Word.
  • Есть объекты, общие для всех приложений. К ним относятся коллекции, CommandBars, Dialogs, Windows объекты Assistant, FileSearch, VBE. Эти объекты хранятся в библиотеке Office, присоединяемой к каркасу каждого документа. Они определяют такие общие для всех документов свойства, как возможность работы с инструментальными панелями, содержащих меню, элементы управления и кнопки; использование стандартных диалогов в документах и другие свойства, задающие, в целом, единый интерфейс документов в среде Office 2000.
  • На общем фоне в Office 97 выделяется объект Access.Application. Структура его бедна. У него нет общих объектов, весьма ограничено число вспомогательных объектов, определяющих специфику данного приложения.
  • (рис 1.7) (рис 1.6) (рис 1.9) (рис 1.8)

    Что же нового появилось в Office 2000? Прежде всего, следует отметить, что все свойства, которыми объекты обладали, у них остались. Но, конечно, появились и новые свойства. Ниже в таблице показаны основные, новые свойства, встроенные в объекты Application в Office 2000.

    Новые свойства объектов Application в Office 2000
    Свойства Word Excel Power Point Access
    AnswerWizard + + + +
    COMAddIns + + + +
    LanguageSettings + + + +
    EmailOptions + - - -
    DefaultWebOptions - + + -
    MsoDebugOptions - - + -

    Появилась возможность подключения COM - объектов, расширяющих функциональные возможности документов; коллекция COMAddIns стала частью библиотеки общих объектов Office 2000. Напомним, что ранее каждое из приложений имело свою специфическую для данного приложения коллекцию AddIns. Каждый из элементов AddIn дополнял приложение новыми функциями, но мог работать только в рамках одного приложения. Этим коллекциям и компонентному программированию будет посвящена отдельная лекция этой книги.

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

    Особо следует отметить и другую линию существенных изменений, направленных на унификацию средств, используемых в разных приложениях. Так объект Access.Application приблизился к своим "братьям" и по структуре свойств в меньшей степени выбивается из общего ряда. Объекты из библиотеки Office, задающие общие для приложений Office 2000 свойства, теперь доступны и в Access Заметим, правда, что сама библиотека Office все еще не подключается по умолчанию при создании каркаса документа Access. Однако, теперь, как и в общем случае, можно щелчком Alt+F11 вызвать Редактор VBE и в меню References подключить эту и другие библиотеки.

    Важно и то, что у объекта Access.Application, как и положено, помимо главных свойств ( Forms, Reports, Modules ) появились на верхнем уровне и дополнительные свойства - участники. Отметим некоторые из них:

  • CodeData. Этот объект позволяет получить доступ к разнообразным коллекциям данных - AllQueries, AllTables, AllViews, AllDataBaseDiagrams, AllStoredProcedures - запросам, таблицам, диаграммам, хранимым процедурам.
  • CodeProject. Этот объект позволяет получать доступ к коллекциям основных объектов приложения - AllForms, AllMacros, AllModules, AllReports, AllDataAccessPages. У объекта есть и методы, позволяющие, например, устанавливать связь с базой данных - OpenConnection, CloseConnection.
  • CurrentData. Представляет косвенную ссылку на текущий объект данных и обладает всеми свойствами объекта CodeData.
  • CurrentProject. Представляет косвенную ссылку на текущий проект и обладает всеми свойствами объекта CodeProject.
  • DBEngine. Объект, представляющий машину вывода со всеми обычными для этого объекта свойствами и методами, как, например, - BeginTrans, CreateDataBase, CreateWorkSpace, OpenConnection - начать транзакцию, создать базу данных, рабочее пространство, открыть связь.
  • DataAccessPages. Эта коллекция объектов, задающих страницы доступа к данным. Каждый из этих объектов содержит такие свойства, как WebOptions, ConnectionString и другие.
  • Вторая группа терминальных свойств

    Объекты Application помимо свойств, заданных вложенными объектами, обладают "терминальными" свойствами. Их задают переменные языка программирования, типы которых непосредственно встроены в язык, - string, integer и т.д. Терминальные свойства также могут быть как специфическими, так и общими для всех приложений, определяя, например, свойства окна, в котором работает приложение. Терминальные свойства просты для понимания, мы не будем на них подробно останавливаться, ограничимся одним примером использования общих свойств. Приведем два макроса, один из которых изменяет размеры окна, предварительно запомнив текущие размеры и состояние окна. Второй из макросов восстанавливает прежние размеры.

    'Объявление переменных на уровне модуля
    Dim LeftW As Long, TopW As Long, HeightW As Long, WidthW As Long
    Dim StateW As WdWindowState
    
    Sub ChangeSizeWindow()
        With Application
    'Запоминаем характеристики окна
            StateW = .WindowState
            LeftW = .Left
            TopW = .Top
            HeightW = .Height
            WidthW = .Width
    ' Изменяем характеристики окна
            .WindowState = wdWindowStateNormal
            .Left = 100
            .Top = 100
            .Height = 400
            .Width = 400
        End With
    End Sub
    
    
    
    Public Sub ResetSizeWindow()
    With Application
    ' Восстанавливаем характеристики окна
            .Left = LeftW
            .Top = TopW
            .Height = HeightW
            .Width = WidthW
            .WindowState = StateW
    End With
    End Sub

    Эту пару макросов можно применять к трем приложениям Office 2000, поскольку в каждом из них объект Application обладает терминальными свойствами Left, Top, Height, Width, WindowState. Единственное, что придется поменять, - тип переменной StateW и задающую статус окна константу wdWindowStateNormal, так как у каждого из приложений свои имена констант и свои типы для них, хотя они и задают одинаковые значения. Заметьте: по имени константы можно определить ее тип и назначение. Так, константы Word начинаются префиксом " wd ", а константы Excel - " xl ".

    Следует отметить, что, Access продолжая выделяться, этих терминальных свойств еще не приобрел.

    Замечание.

    Все примеры этой книги мы старались проверить непосредственно на машине. С этой целью, как правило, для проверки соответствующего примера в тестовом документе создавалась командная кнопка, в ответ на щелчок которой вызывался соответствующий макрос, текст которого и приводится в книге. На рис. 1.10 показан такой тестовой документ, для проверки примеров этой лекции.

    (рис 1.10) Тестовый документ с командными кнопками

    Методы объектов Application

    Казалось бы, объекты Application не должны иметь много методов, а среди имеющихся методов большая часть должна быть общей для приложений разных типов. Ведь специфика приложения должна проявляться на более низком уровне иерархии, когда начинается работа, например, с документами Word или рабочими книгами Excel. Но это не так, - реально методов много, а общих методов мало. Более того, даже методы Activate, Run, Quit, имеющиеся у всех приложений, совпадающие по именам и предназначенные для решения стандартных задач (активизация приложения, запуск макроса, выход из приложения) организованы по-разному. Так, метод Quit() в Excel не имеет параметров - он, естественно, завершает приложение. А вот в приложении Word у этого метода 3 параметра: Quit([SaveChanges], [OriginalFormat], [RouteDocument]), - позволяющие в момент выхода указать, сохранять ли сделанные изменения и их формат, пересылать ли документ всем, кто работает с ним.

    Лишь приложение Power Point "правильно" устроено с нашей точки зрения, - его объект Application имеет всего четыре метода; помимо трех методов, только что перечисленных, у него еще есть метод Help. Это тоже один из общих методов, которого нет только у приложения Access.

    Из общих в Office 2000 методов для Word, Access и Excel отметим группу DDE-методов, обеспечивающих динамический обмен данных. Word и Excel имеют общий метод OnTime, о котором стоит рассказать подробно. Он позволяет запустить некоторый макрос в заданное время. Каждое утро, например, можно запускать макрос, позволяющий провести антивирусную профилактику, сохранить резервные копии и т. п. Синтаксис метода в приложении Word таков:

    OnTime (When, Name, Tolerance)

    Первый обязательный параметр When задает время запуска - некоторое выражение, значением которого является строка, задающая время. При задании этого параметра часто используются функция Now, которая возвращает текущее время, и функции TimeValue и TimeSerial, преобразующие время, заданное в относительно произвольной форме к фиксированному стандарту.

    Параметр Name - также обязательный - задает имя запускаемого макроса. Макрос должен быть доступен как в момент выполнения процедуры OnTime, так и когда наступает время его выполнения, указанное в параметре When. Поэтому разумно такие макросы помещать, например, в проект Normal, доступный для всех приложений Word.

    Параметр Tolerance задает диапазон времени, в течение которого есть смысл запустить макрос, если он не смог быть запущен в указанный параметром When момент. Причин, по которым макрос нельзя запустить в точно указанный срок, может быть много, - например, идет модальный диалог, который нельзя прервать до его завершения.

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

    Sub InTime()
    	'Запуск одного из двух макросов "Приветствие"
    	'Один запускается по утрам в 10.00, другой - через 1 минуту,
    	'начиная отсчет от момента выполнения метода OnTime
    	If Now < "10:00:00" Then
    			Application.OnTime TimeValue("10:00 am"), "Morning"
    	Else
    			Application.OnTime Now + TimeValue("00:01:00"), "Hello"
    	End If
    End Sub

    Заметьте: запускается только один из макросов. "Завести два будильника", дважды вызвав метод OnTime, нельзя - ведь только один таймер следит за запуском макроса. Пока "заведенный" макрос не будет исполнен, любая попытка установить время для запуска следующего макроса приведет к отмене предыдущего указания.

    Для полноты картины приведем тексты макросов-приветствий:

    Sub Morning()
    	' Утреннее приветствие
    	MsgBox Prompt:="Привет! Я рад, работать с Вами!", Buttons:=vbOKOnly
    End Sub
    
    Sub Hello()
    	'Приветствие
    	MsgBox Prompt:="Привет! Будем работать!", Buttons:=vbOKOnly
    End Sub

    Итак, подводя итоги, отметим, что только объект Power Point.Application имеет всего четыре метода. Остальные объекты Application имеют десятки методов, большей частью отражающих специфику приложения. Например, в Office 2000 объект Access.Application имеет:

  • Группу из 9 методов Create, позволяющих программно создать проект, элемент управления, форму, отчет и другие элементы приложения.
  • Группу D - функций, общих с Excel, позволяющих работать с запросами над списками Excel.
  • Группу Get и Set - методов, позволяющих, например, получить или установить те или иные опции.
  • Методы Open, Close, New, позволяющие открывать, закрывать или делать текущей новую базу данных.
  • Другие методы.
  • Следует понимать причину "изобилия" методов у объектов Application. Дело в том, что большинство методов, это, фактически, методы объектов нижних уровней, вынесенные на верхний уровень иерархии.

    Один и тот же метод X может быть определен как для объекта Application, так и для объектов разных классов, вложенных на разных уровнях иерархии. Иногда это позволяет выполнять массовые операции над всеми объектами, входящими в иерархию. Так, метод Calculate в Excel применим к объектам Application, WorkBook и Worksheet. Вызов Application.Calculate приведет к запуску вычисления формул всех рабочих листов всех рабочих книг.

    Но будьте осторожны: методы - "тезки" могут отличаться параметрами и реализацией. Например, методы проверки правописания и грамматики CheckSpelling и CheckGrammar определены для трех объектов Word: Application, Document и Range. Вызванные объектами Document и Range, они проверяют текст в диапазоне, связанном с объектом, вызвавшим метод. А у одноименных методов объекта Application появляется дополнительный параметр, задающий проверяемую строку.

    Еще один пример - метод Move, которым обладают объекты:

  • Application, Task, Range, Selection - в приложении Word;
  • Chart, Charts, Worksheet, Worksheets, Sheets в приложении Excel;
  • общие объекты Assistant, CommandBarControl из библиотеки объектов Office;
  • Control, Controls из библиотеки объектов MSForms.
  • За общим именем скрываются похожие, но разные по количеству параметров и по действию методы. В ООП одноименные методы одного или разных классов, различные по количеству и типам параметров и (или) реализации, называются перегруженными. В Office 2000 широко применяется перегрузка методов. С этим часто приходится сталкиваться при получении справок в электронной документации, например, по уже упомянутому методу Move, когда приводятся несколько его перегруженных вариантов. В этом случае дается список классов, обладающих данным методом. Выбрав класс, можно получить справку по конкретной реализации метода в данном классе.

    Осталось еще рассказать, какие новые методы появились у Application -объектов приложений Word, Access и Excel в Office 2000 в сравнении с предыдущей версией Office 97. Общих новых методов нет.

    В приложении Word у объекта Application появилось 8 новых методов. Два из них расширяют набор метрических преобразований, четыре определены над клавиатурой и связаны с расширенной поддержкой национальных языков в Office 2000. Еще один метод следует упомянуть подробнее, - речь идет о функции DefaultWebOptions, возвращающей объект подобного класса. Если взглянуть на ранее приведенную таблицу новых свойств, то можно заметить, что приложения Power Point и Excel имеют новое свойство, возвращающее объект этого класса. Приложение Word вместо этого имеет метод, возвращающий тот же объект. Один Access пока что не имеет ни подобного свойства, ни метода.

    В приложении Excel, как ни странно, нет новых методов, Более того, исчезли два старых метода: CentimetersToPoints, InchesToPoints, занимающихся метрическими преобразованиями. Вместо того, чтобы добавлять новые методы этой группы, как это сделано в Word, решили убрать эту группу методов из ведения объекта Application.

    Больше всего новых методов появилось у объекта Access.Application, - их 18. Прежде всего, пополнилась группа Create - методов. Теперь можно создавать не только формы и отчеты, но и проекты ( CreateAccessProject ), страницы доступа ( CreateDataAccessPage ), элементы управления с расширенным набором свойств, размещаемые, возможно, в отчете( CreateControlEx, CreateReportControlEx ). С проектами работают еще два метода, - OpenAccessProject, NewAccessProject. Несколько методов добавлено для работы с текстами. Детали оставим на будущее.

    События объектов Application

    У объекта Access.Application событий нет. Все события вынесены на более низкий уровень иерархии и возникают при работе с документами Access - отчетами, формами и т.д.

    Объекты Application приложений Word, Excel и Power Point имеют примерно одинаковый набор событий. Фактически эти события возникают при работе с объектами нижних уровней иерархии - окнами, документами Word, рабочими книгами и страницами ( Sheets ) Excel, презентациями и слайдами Power Point. Всякий раз, когда окно или тот или иной документ создается, открывается, изменяется, закрывается, - возникает соответствующее событие, которое можно обработать. Обработчик события можно связывать непосредственно с самим объектом, при работе с которым событие возникло. Но иногда удобнее вынести обработчик на верхний уровень приложения и связать его с объектом Application. Это особенно полезно, если один и тот же обработчик применяется ко всем документам приложения.

    Совместная работа приложений. Создание объектов Application. Раннее и позднее связывание

    Мы уже не раз говорили, что эффективность работы в среде Office 2000 во многом определяется возможностью совместной работы его приложений. С программистской точки зрения это означает, что в документе одновременно определены несколько объектов Application, задающих совместно работающие приложения. Давайте рассмотрим, как обеспечивается такая возможность. При открытии какого - либо из приложений, например, документа Word по умолчанию считается определенным соответствующий объект Application, а следовательно и все объекты, в него вложенные. Более того, определены и все объекты, входящие в каркас документа, построенный по умолчанию.

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

  • Расширить каркас документа Word, установив ссылки на библиотеки, содержащие приложения Excel и Access . Напомним, что это делается в редакторе VBE в окне References меню Tools.
  • Объявить объекты (указатели на объекты) соответствующего класса.
  • Создать объекты и связать указатели с вновь созданными объектами.
  • Когда корневой объект Application создан и доступен, то автоматически становятся доступными все вложенные в него объекты, так что теперь с приложением можно работать в обычном режиме, вызывая свойства и методы его объектов. При объявлении объектов возможны варианты. При этом следует помнить, что объекты в VBA задаются с помощью указателей. Рассмотрим три возможных варианта объявления:

  • Dim MyXlApp As Object, MyAcApp As Object Этот вариант задает так называемое позднее связывание. На этапе объявления известно, что MyApp переменные являются объектами, а точнее, указателями на объекты, но еще не известно с объектами какого класса они будут связаны. Это станет известно динамически, в ходе выполнения программы, когда реально будет создан объект - экземпляр соответствующего класса и наш указатель получит на него ссылку. Для программиста эти переменные являются нетипизированными указателями.
  • Dim MyXlApp As Excel.Application, MyAcApp As Access.Application Это объявление задает раннее связывание. Наши переменные теперь представляют собой типизированные указатели. И уже на этапе объявления известно, что в дальнейшем они будут связаны с объектами соответствующего класса. Чтобы при этом объявлении не возникло конфликтов, конечно же, необходимо предварительно подключить соответствующую библиотеку. Важно также понимать, что на этапе объявления память выделена только указателям. Сами объекты еще не созданы, и потому значения указателей не определены. Объекты еще предстоит создать по ходу выполнения программы и указатели должны быть связаны с ними.
  • Dim MyXlApp As New Excel.Application, MyAcApp As New Access.Application В этом случае раннее связывание реализуется в полном объеме. Создается указатель, благодаря спецификатору New создается сам объект, и указатель получает ссылку на вновь созданный объект.
  • Эти три варианта характерны не только при работе с объектами Application, а во всех случаях работы с объектами. Конечно же, в большинстве случаев предпочтительнее третья конструкция, когда создание объекта и указателя совмещаются в одном операторе. В Office 2000 такая конструкция является допустимой для объектов Application и ее разумно использовать.

    Заметьте, что не все приложения допускают конструкцию New для создания Active X объектов, каковыми являются объекты Application. В ряде случаев для создания Active X объектов, хранящихся в отдельных файлах, следует использовать метод CreateObject, первый параметр которого задает имя класса объекта. Этот метод следует выполнить в нужный момент, связав заодно указатель с вновь созданным объектом. Конечно, и в Office 2000 допустимо создать объекты Application следующим образом:

    Set MyXlApp = CreateObject("Excel.Application ")
    Set MyAcApp = CreateObject("Access.Application ")

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

    В заключение рассмотрим пример, иллюстрирующий работу трех приложений: Word, Excel и Access:

    Public Sub WorkWithExcel()
    'НЕ забудьте включить ссылку на Excel в меню References
     'Объявление и создание объектов Excel.Application
            Dim MyXlApp As New Excel.Application
        'Работа с приложением Excel
        With MyXlApp
                .Visible = True
            'Excel появился на линейке и его можно раскрыть
             'Добавить новую книгу
           .Workbooks.Add
                'Теперь можно работать и с ячейками данной книги
                .Range("A1") = "Hello!"
                'Идет работа с книгой
                .Range("B1") = "By-By"
            .Workbooks(1).Activate
             'Закрываем открытую книгу
             MsgBox ("Закрываем рабочую книгу Excel?")
            .Workbooks(1).Close
            'Будет задан вопрос о необходимости сохранения книги
             'Закрываем приложение
         .Quit
        End With
    End Sub
    
    Public Sub WorkWithAccess()
    'НЕ забудьте включить ссылку на Access и Dao 3.6 в меню References
    'Приложение Access и его компоненты:
    'База данных, форма и путь к базе
    Dim MyAc As New Access.Application
    Dim MFDb As Database
    Dim FormPoetAges As Form
    Dim PathDb As String
    'Открываем базу данных Access
        PathDb = "E:\O2000\CD2000\Ch1\AgeOfPoet.mdb"
        MyAc.OpenCurrentDatabase (PathDb)
        Set MFDb = MyAc.CurrentDb
    'Открываем форму
    	MyAc.DoCmd.OpenForm ("AgeOfPoets")
    	Set FormPoetAges = MyAc.Forms("AgeOfPoets")
    	MyAc.Visible = True
    	FormPoetAges.SetFocus
    
    'Закрываем базу данных
    	MsgBox ("Закрываем базу данных Access?")
    	MyAc.Quit
    End Sub

    Макросы WorkWithExcel и WorkWithAccess могут быть вызваны из приложения Word. В наших тестовых примерах мы вызывали их в ответ на щелчок соответствующих командных кнопок. Заметьте, второй пример довольно содержателен. Здесь показано, как, не выходя из документа Word, просматривать и редактировать данные формы, созданной в приложении Access для работы с базой данных.

    На этом мы прервем знакомство с корневыми объектами Application. Помните, явно или неявно они всегда будут присутствовать в наших примерах.

    Коллекции в Office 2000

    Почти половина классов объектов в Office 2000 являются коллекциями. Это объясняется тем, что элементы большинства классов можно объединить в упорядоченную совокупность, получив тем самым новый класс - коллекцию элементов. Коллекция это способ организации динамической структуры данных, и потому методы коллекций во многом схожи между собой. Но поскольку специфика элементов различна, то, как следствие, коллекции имеют и специальные свойства и методы. В современных языках программирования коллекции становятся столь же употребительной частью языка, как массивы. Рассмотрим некоторые коллекции объектов Office 2000 и те вариации, которыми они отличаются друг от друга.

    Коллекции объектов Office 2000

    Мы уже говорили, что коллекцию можно рассматривать, как структуру данных, способ их организации. При таком подходе свойства и методы коллекции определяют эту структуру и не учитывают специфику объектов, составляющих коллекцию. Этот подход характерен для класса Collection языка VBA. В других приложениях Office 2000 преобладает несколько иная точка зрения: здесь для большинства коллекций учитываются особенности их объектов, что находит отражение в появлении специфических свойств и методов у различных коллекций. Сейчас мы подробно рассмотрим некоторые коллекции объектов Office 2000. Выбранные для ознакомления коллекции интересны сами по себе, ввиду их широкого использования. С другой стороны, нам важно дать общее представление о возможных вариациях при организации специальных коллекций. Надеемся, приведенных примеров будет достаточно для ориентации во всех имеющихся классах коллекций.

    Коллекции Excel: Workbooks, Sheets

    "Excel позволяет одновременно работать с одной или несколькими рабочими книгами. Каждая книга состоит из одного или более листов. Листы бывают разных типов: рабочие листы, диаграммы, модули, листы макросов. Один из наиболее употребительных - рабочий лист - состоит из совокупности ячеек. Мощь Excel во многом определяется операциями, которые можно выполнить над ячейками рабочего листа…"

    Примерно так можно было бы начать описание Excel. Мы начали его с введения основных понятий. При объектном подходе каждому понятию ставится в соответствие класс объектов. В терминах классов и объектов это же описание Excel может выглядеть так:

    "Объект Application. Excel, представляющий приложение Excel, имеет свойство-участник (встроенный объект) WorkBooks, возвращающее объект WorkBooks - коллекцию всех открытых рабочих книг. Каждый элемент коллекции - рабочая книга - является объектом класса WorkBook.

    Объект WorkBook, представляющий одну рабочую книгу, имеет свойство Sheets. При обращении к этому свойству возвращается объект Sheets - коллекция листов данной книги. Каждый элемент коллекции - лист - имеет свой тип и потому является объектом, например, класса Worksheet (рабочий лист) или Chart (диаграмма).

    Объект Worksheet, представляющий один рабочий лист, имеет свойство Cells, возвращающее объект Range. Используя этот объект, можно задавать как все ячейки рабочего листа - всю таблицу, так и любую ее часть…"

    Как видите, при объектном подходе к изучению Excel мы начинаем с введения классов объектов и заметьте, коллекции появляются уже на первых шагах. Коллекции WorkBooks, Worksheets представляют центральные понятия Excel. С них мы и начнем подробное рассмотрение коллекций объектов Office 2000.

    Коллекция Workbooks

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

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

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

    Add(Template)

    Необязательный параметр Template задает шаблон создания книги. Этот параметр может быть строкой, задающей имя файла, который хранит некую рабочую книгу. В этом случае книга играет роль шаблона для создания новой книги. Параметр Template может также принимать значение одной из предопределенных констант: xlWBATChart, xlWBATWorksheet, xlWBATExcel4IntlMacroSheet, xlWBATExcel4MacroSheet. В этом случае создается рабочая книга с одним листом, тип которого и задает константа. Если же параметр Template опущен, то создается книга с несколькими пустыми листами, число которых устанавливает свойство SheetsInNewWorkbook.

    У метода Open более десяти параметров. Обязательным является только первый - FileName. Он должен быть строкой, которая задает имя файла, хранящего книгу.

    Чтобы удалить рабочую книгу из коллекции, нужно закрыть соответствующий файл (в коллекцию входят лишь открытые рабочие книги). Закрытие книги и, следовательно, ее удаление выполняет метод Close. Он определен как для коллекции, так и для рабочей книги - объекта класса WorkBook. В первом случае метод Close не имеет параметров и закрывает всю коллекцию - все рабочие книги. Чаще всего этот метод вызывается объектом - рабочей книгой для своего закрытия. В этом случае его синтаксис:

    Close(SaveChanges, FileName, RouteWorkbook)

    Все параметры являются необязательными. Первый - булевого типа: если его значение True, сделанные изменения будут сохранены, в противном случае они не сохраняются. Когда же этот параметр опускается, то при выполнении появляется соответствующее диалоговое окно, в котором свой выбор может сделать пользователь. Второй параметр - FileName - необходим, если речь идет о закрытии новой книги, с которой еще не связано имя файла. Если параметр опущен, а указание имени файла необходимо, то, естественно, появляется диалоговое окно. Третий параметр, как и первый, булевого типа. Он задается, когда рабочая книга может быть направлена нескольким участникам для поочередной работы с ней. Если его значение True, книга направляется следующему по списку ее разработчику.

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

    Item(Index)

    Индекс может указывать порядковый номер книги в коллекции, либо быть именем книги. Заметьте, имя книги это имя файла, в котором она хранится. Когда создается новая пустая книга, то ей по умолчанию система присваивает имя типа " BookN ". При сохранении книги в файле это имя может быть изменено. Метод Item является методом по умолчанию и чаще всего опускается. В этом случае индекс связывается с самим объектом - коллекцией рабочих книг.

    Свойство Count возвращает количество элементов коллекции. Доступно только для чтения, имеет тип возвращаемого значения Long.

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

  • Свойство Application возвращает корневой объект Application.
  • Свойство Creator аналогично свойству Application. Оно возвращает код приложения (32-битное целое), который используется при работе с Macintosh.
  • Свойство Parent возвращает родительский объект (для коллекции WorkBooks это все тот же объект Application ).
  • Метод OpenText является модификацией метода Open. Он создает новую рабочую книгу с одной страницей, используя для ее создания текстовый файл. В процессе открытия происходит анализ и разбор данных, записанных в текстовом файле. Метод имеет 13 параметров, из которых обязателен лишь первый - FileName, задающий имя текстового файла.
  • Приведем теперь пример программы, позволяющий продемонстрировать детали работы с коллекцией WorkBooks. Наша коллекция будет включать как новые, создаваемые в программе, так и ранее существовавшие книги. Книги будут добавляться в коллекцию и удаляться. Отладочная печать позволит проследить за этим процессом.

    Public Sub WorkWithbooks()
    ' Работа с коллекцией книг
    Dim N As Long, i As Byte
    Dim PathDir As String
    PathDir = "e:\O2000\CD2000\Ch1\"
    With Workbooks
        N = .Count
        Debug.Print "Число рабочих книг в коллекции Workbooks "  _
        "при открытии приложения Excel = ", N
        ' Добавление 2-х новых книг
        .Add
        .Add
        'Добавление двух существующих книг
        .Open (PathDir  "BookThree.xls")
        .Open (PathDir  "BookFive.xls")
        N = .Count
        Debug.Print "Число книг после 2-х вызовов методов Add и Open =", N
        Debug.Print "Имена книг в коллекции:"
        For i = 1 To .Count
            Debug.Print .Item(i).Name
        Next
        'Закрытие двух книг и, следовательно, удаление их из коллекции
        .Item(2).Close
        .Item(3).Close
        N = .Count
        Debug.Print "Число книг после двух вызовов метода Close =", N
        Debug.Print "Имена книг, оставшихся в коллекции:"
        For i = 1 To .Count
            Debug.Print .Item(i).Name
        Next
    End With
    
    End Sub

    Вот результаты отладочной печати:

    Число книг в коллекции WorkBooks при открытии приложения Excel =1 
    Число книг после 2-х вызовов методов Add и Open =        5 
    Имена книг в коллекции:
    BookOne.xls
    Book4
    Book5
    BookThree.xls
    BookFive.xls
    Число книг после двух вызовов метода Close =             3 
    Имена книг, оставшихся в коллекции:
    BookOne.xls
    Book5
    BookFive.xls

    Поясним пример. При открытии Excel коллекция WorkBooks состоит из одной открытой книги, в данном случае - книги с именем BookOne. Затем метод Add добавил в коллекцию две новые книги, которые получили имена " Book1 " и " Book2 " соответственно. Еще две книги появляются в коллекции при открытии существующих книг. Затем две книги закрываются, следовательно, удаляются из коллекции. Обратите внимание, удаляются 2-я и 4-я книги коллекции, хотя индексы удаляемых книг имеют значение 2 и 3. Это связано с тем, что после каждого удаления элемента коллекции происходит перенумерация, и книги получают новые индексы.

    Если при работе с элементами коллекции выполняется операция удаления, то работать с индексами элементов крайне опасно, предпочтительнее для задания элементов указывать их имена!

    Коллекция Sheets

    Коллекция Sheets представляет коллекцию листов двух типов: рабочих листов и диаграмм, - так что каждый элемент коллекции может быть объектом одного из двух классов: Worksheet или Chart. Наряду с коллекцией Sheets существуют коллекции Worksheets и Charts. Они представляют коллекции рабочих листов и диаграмм, выделенных из коллекции Sheets. Но объекты, задающие эти коллекции, принадлежат классу Sheets и используют его свойства и методы. К их рассмотрению мы и переходим.

    Когда создается или открывается рабочая книга, она содержит уже некоторое число листов. Так что коллекция Sheets не пуста в момент открытия книги. Для добавления новых листов в книгу используется знакомый нам метод Add:

    Add(Before,After,Count,Type)

    Все параметры являются необязательными. Первые два - Before и After задают позицию вставки листа - индекс листа, перед или после которого вставляется новый лист. Из этих параметров одновременно может быть задан только один. Если оба параметра опущены, вставка производится перед активным листом данной книги. Параметр Count определяет количество вставляемых листов (по умолчанию - 1). Последний параметр определяет тип вставляемых листов, задаваемый соответствующей константой: xlWorksheet, xlChart, xlExcel4MacroSheet, xlExcel4IntlMacroSheet (по умолчанию - xlWorksheet ).

    Замечание:

    Рабочая книга имеет листы четырех типов. Но при вызове свойства Sheets объекта WorkBook возвращается объект класса Sheets с листами только двух типов. Чтобы получить листы других типов, нужно обратиться к другому свойству объекта WorkBook, например Excel4IntlMacroSheet, возвращающему также объект класса Sheets, но содержащий листы с так называемыми международными макросами, созданными под Excel4.

    Следует обратить внимание на то, что:

  • в методе Add класса Sheets нет параметра, задающего ключ элемента. Однако фактически ключ задается. Его роль играет имя листа, заданное в виде свойства Name, имеющееся у листа каждого типа. Имя листа наряду с числовым индексом можно использовать для поиска листа в методе Item.
  • Из коллекции Sheets листы удаляются методом Delete, не имеющим параметров. В такой форме этот метод имеют многие классы объектов, в том числе Sheets, Worksheet и Chart. Если Delete вызывает объект Sheets, удаляется вся коллекция; если же его вызывают объекты Worksheet или Chart, удаляется соответствующий лист.
  • Получить доступ к элементу позволяет метод (свойство) Item:
    Item(Index)
    Параметр Index задает имя или порядковый номер листа. Метод Item является методом по умолчанию и может быть опущен.
  • Напомним, что иногда бывает трудно провести четкую грань, отличающую метод от свойства. Item является классическим примером подобной ситуации и потому в одной части документации он называется методом, а в другой - свойством.

    Класс Sheets имеет уже известные нам свойства: Application, Creator, Parent и Count. Рассмотрим новые возможности, появившиеся у коллекции Sheets:

  • Свойство Visible - имеет значение True, если объект видимый, и False - в противном случае. Для рабочих листов и диаграмм это свойство может быть также задано константой xlVeryHidden (упрятано, да не просто, а очень уж). Если лист имеет это свойство, он становится невидимым и пользователь никак не сумеет его увидеть, пока программно это свойство не будет установлено в True. Тип свойства двоякий: Boolean или Long.
  • Свойства HPageBreak и VPageBreak - возвращают соответственно коллекции горизонтальной и вертикальной разбивки листа на страницы.
  • Метод Copy - позволяет создать новый лист книги, копируя содержимое уже имеющегося листа. Его синтаксис:
    Copy(Before, After)
    Параметры имеют привычный смысл, указывая точку вставки копируемого листа. Только один из них может быть задан при вызове метода. Метод Copy, вызванный без параметров, копирует содержимое объекта в буфер.
  • Метод Move - модификация метода Copy, позволяет передвинуть лист книги в новое положение. Его синтаксис:
    Move(Before,After)
    Параметры имеют тот же смысл, что и в методе Copy.
  • Метод Paste - копирует содержимое буфера. Параметров не имеет.
  • Метод Select - выделяет объект, его вызвавший. Методом Select обладают объекты многих классов. Если его вызывает коллекция Sheets, метод используется без параметров и выделяет все листы коллекции. Если же он вызван отдельным листом, то может иметь параметр:
    Select(Replace)
    Параметр Replace - булевого типа: если он равен True, происходит замена объекта Selection, и выделенным становится лист, вызвавший метод. Если же значение параметра - False, происходит расширение области выделения, так чтобы она включала ранее выделенный объект и новый лист.
  • Методы PrintPreview и PrintOut - позволяют осуществлять просмотр печати и печать объекта, вызвавшего метод. Как и большинство других рассматриваемых методов, они принадлежат многим классам, в том числе классам Sheets, Charts, Chart, Worksheets, Worksheet, WorkBook и др. Его синтаксис:
    PrintOut(From, To, Copies, Preview, ActivePrinter, PrintToFile, Collate)
    Все параметры необязательны. Первые два задают начальную и конечную страницу печати. Если их нет, печать идет с первой по последнюю страницу. Параметр Copies, если указан, задает количество копий при печати. Если значение булевого параметра Preview - True, предварительно происходит просмотр печати, если же параметр опущен или равен False, просмотра перед печатью нет. Параметр ActivePrinter устанавливает имя активного принтера. Значение булевого параметра PrintToFile - True, если предполагается, что результаты печати посылаются не на принтер, а записываются в файл. При этом появляется диалоговое окно, в котором пользователь задает имя файла, хранящего результаты печати. Если значение параметра Collate задано True, будут сличаться результаты копий, выводимых на печать.
  • Метод FillAcrossSheets копирует содержимое области, заданной объектом Range на рабочие листы коллекции. Его синтаксис:
    FillAcrossSheets(Range, Type)
    Параметр Range указывает область копирования. Она должна принадлежать одному из листов коллекции. Этот параметр обязателен. Необязательный параметр - Type - указывает, как происходит копирование. Он может принимать значение, заданное одной из следующих констант: xlFillWithAll, xlFillWithContents или xlFillWithFormulas. Значение по умолчанию - xlFillWithAll.
  • В заключение приведем пример, демонстрирующий большинство методов этой коллекции.

    Public Sub WorkWithSheets()
    'Работа с коллекцией Sheets - листами рабочей книги
    Dim N As Long, i As Byte
    Dim X As Variant
    'Активизация книги Book2
    Workbooks("Book2").Activate
    With ActiveWorkbook.Sheets
        N = .Count
        Debug.Print "Число листов при первоначальном открытии" _
             "книги = ", N
        Debug.Print "Имена листов:"
        For i = 1 To .Count
           Debug.Print .Item(i).Name
        Next
        ' Переименование листов
        .Item(1).Name = "Two"
        .Item(2).Name = "Four"
        .Item(3).Name = "Six"
        'Добавление листов One, Three, Five
        .Add Before:=.Item("Two")
        .Add After:=.Item("Two"), Type:=xlChart
        .Add After:=.Item("Four"), Type:=xlExcel4MacroSheet
        .Item(1).Name = "One"
        .Item(3).Name = "Three"
        .Item(5).Name = "Five"
         N = .Count
         Debug.Print "Число листов книги после вставки" _
                 "3-х листов =", N
         Debug.Print "Имена и типы листов после переименования:"
         For i = 1 To .Count
             Debug.Print .Item(i).Name, .Item(i).Type
         Next
         'Удаление 3-го и 5-го листов
         .Item("Three").Delete
         .Item("Five").Delete
         'Работа с первым листом
         .Item("One").Activate
        'Запуск макроса Fibonachi, заполняющего область листа A1:A20
        'последовательностью чисел Фибоначчи
         Fibonachi
        'Копирование первого листа на вновь создаваемый третий лист
         .Item("One").Copy After:=.Item("Two")
         'Переименование и перемещение листа
         ActiveSheet.Name = "Seven"
         .Item("Seven").Move After:=.Item("Six")
        'Копирование области одного листа на последовательность листов
        X = Array("One", "Four", "Six")
        Sheets(X).FillAcrossSheets Range:=Worksheets("One").Range("A1:A20")
        Debug.Print "Имена,типы листов и содержимое двадцатой ячейки:"
        For i = 1 To .Count
            Debug.Print .Item(i).Name, .Item(i).Type, _
                .Item(i).Range("A20").Value
        Next
    End With
    End Sub

    Работая с тестовым документом - книгой BookOne. Мы последовательно щелкали командные кнопки, запускающие процедуры WorkWithBooks и WorkWithSheets. Вот результаты отладочной печати при работе последней процедуры:

    Число листов при первоначальном открытии книги = 3 
    Имена листов:
    Sheet1
    Sheet2
    Sheet3
    Число листов книги после вставки 3-х листов = 6 
    Имена и типы листов после переименования:
    One           -4167 
    Two           -4167 
    Three          3 
    Four          -4167 
    Five            3 
    Six            -4167 
    Имена, типы листов и содержимое двадцатой ячейки:
    One          -4167          6765 
    Two          -4167         
    Four          -4167          6765 
    Six            -4167          6765 
    Seven       -4167          6765

    Кратко прокомментируем работу программы. Вначале активизируется книга с именем Book2 из коллекции книг, созданных предыдущим макросом. Эта книга содержит три листа со стандартными именами: Sheet1 -Sheet3. Мы добавляем в эту книгу еще три листа разных типов и переименовываем все листы, давая им имена от One до Six. Четыре листа книги являются рабочими листами и имеют тип xlWorksheet (значение константы -4167 ). Третий лист - это лист диаграммы типа xlChart, а пятый является листом макросов и имеет тип xlExcel4MacroSheet.

    Замечание:

    В Office 97 и Бета версии Office 2000 тип листа диаграммы (свойство Type ) устанавливался неверно. Вместо правильного значения, равного -4109, устанавливалось значение 3, что соответствует листу макроса. В процессе тестирования Office 2000 мы сообщили об этой ошибке и надеемся, что в заключительной версии она уже исправлена.

    Затем третий и пятый лист удаляются, и в книге остаются только рабочие листы. Следующие шаги программы демонстрируют работу методов Copy и Move. Вначале активизируется первый лист, вызывается макрос Fibonachi, заполняющий последовательностью чисел Фибоначчи область листа - ячейки A1:A20. Затем создается копия этого листа, и вновь созданный лист - One(2) - помещается после второго листа книги. Он переименовывается, получает имя Seven и перемещается, заняв позицию после листа Six. Метод FillAcrossSheet позволяет скопировать область одного листа в соответствующие области нескольких листов той же книги. Для этого вначале создается массив X с именами листов, в которые будут копироваться данные. Обратите внимание на этот важный, часто используемый метод. Заметьте: в список массива X должен быть включен и лист One, с которого будет производиться копирование.

    Коллекции Word: Documents, Paragraphs и другие

    Word позволяет одновременно работать с одним или несколькими документами. Документы и коллекция документов - это центральные понятия Word. Классы Document и Documents играют для Word ту же роль, что и классы WorkBook и WorkBooks для Excel. Документ Word организован довольно сложно. Текст - основа большинства документов - может быть дополнен рисунками и таблицами, с ним могут быть связаны комментарии и исправления, сноски и колонтитулы и т. д. Но об этом речь впереди, а пока чуть подробнее поговорим о тексте. Конечно, текст можно рассматривать как последовательность символов, его составляющих. Но ведь куда как часто мы оперируем с более крупными единицами! Word использует привычные понятия: символы, слова, предложения, абзацы, разделы.

    Существуют понятия - существуют и классы, соответствующие этим понятиям. Объект Application. Word, представляющий приложение Word, имеет свойство (встроенный объект) Documents. При обращении к свойству возвращается объект класса Documents - коллекция всех открытых документов. Элемент коллекции - документ - это объект класса Document.

    Объект Document, представляющий один документ, имеет свойства:

    Свойство Возвращает
    Characters объект класса Characters, представляющий коллекцию символов текста документа
    Words объект, представляющий коллекцию слов
    Sentences объект, представляющий коллекцию предложений
    Paragraphs объект, представляющий коллекцию абзацев
    Sections объект, представляющий коллекцию разделов или секций документа
    ListParagraphs объект, представляющий коллекцию списков, входящих в текст документа

    Конечно, это лишь часть многочисленных свойств, связанных с текстом документа. Заметьте: данными свойствами обладает не только сам документ. Ими обладают и объекты Selection и Range, представляющие части документа. При этом возвращаемые объекты представляют соответствующие коллекции данной части документа.

    Казалось бы, раз есть коллекции Characters или Words, то должны существовать и классы Character и Word, представляющие отдельный символ или отдельное слово. Но это не так. Элементами коллекций Characters, Sentences и Words являются объекты класса Range. Нет операций, отдельно определенных над символами, словами или предложениями, - они определены над интервалами, последовательностью символов, представляемых объектом Range. Ситуация здесь подобна Excel, где элементами коллекции Cells являются не ячейки, а все тот же объект Range.

    Абзацу и разделу соответствуют свои классы объектов - Paragraph и Section соответственно. Но у нас сейчас разговор пойдет не о классах отдельных объектов, а о коллекциях. Мы начнем с коллекции документов.

    Коллекция Documents

    Коллекция Documents представляет все открытые документы Word. По своим свойствам и поведению она напоминает коллекцию WorkBooks, представляющую все открытые рабочие книги Excel. Поэтому мы будем часто ссылаться на уже описанные свойства и методы коллекции WorkBooks.

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

  • Add - добавляет новые пустые документы;
  • Open - открывает файл, содержащий существующий документ и автоматически добавляет его в коллекцию.
  • Метод Add имеет синтаксис:

    Add(Template,NewTemplate)

    Параметр Template, задающий шаблон открытия документа, является строкой с именем файла, хранящего шаблон. Параметр не является обязательным и, если он опущен, используется стандартный шаблон Normal (файл Normal. dot). Второй параметр (тоже необязательный) - NewTemplate - булевого типа; он равен True, если документ открывается, как шаблон. Так что коллекция Documents содержит не только документы, но и шаблоны.

    У метода Open десять параметров. Обязательным является только первый - FileName ; он задает имя файла, содержащего документ (шаблон). Остальные параметры определяют режимы открытия: пароль, статус файла, преобразование формата при открытии и т. п.

    Документ удаляется из коллекции при его закрытии. Вне коллекции не может существовать открытый документ. Метод Close закрывает документ и одновременно удаляет его из коллекции. Его синтаксис:

    Close(SaveChanges, OriginalFormat, RouteDocument)

    Все параметры являются необязательными. Первый указывает действия, предпринимаемые при закрытии документа, и может быть одной из констант: wdSaveChanges, wdDoNotSaveChanges, wdPromptToSaveChanges. В зависимости от константы сделанные в документе изменения будут сохранены, проигнорированы или решение будет предоставлено пользователю в режиме диалога. По умолчанию изменения сохраняются при закрытии документа. Параметр OriginalFormat указывает формат сохранения документа и может быть одной из констант: wdWordDocument, wdOriginalFormat, wdPromptUser. В первом случае при сохранении используется формат документов Word, во втором - оригинальный формат документа - тот, что он имел при открытии; в последнем случае решение принимает пользователь в режиме диалога. По умолчанию предполагается формат документа Word. Третий параметр - булевого типа - равен True, если документ после закрытия направляется следующему пользователю, который принимает участие в работе над этим документом. Данный параметр имеет смысл лишь при коллективной работе над документом в сети. По умолчанию он равен False.

    Метод Save позволяет сохранять документы (шаблоны) без закрытия и удаления из коллекции. Этот метод имеют как объекты класса Document, так и коллекции - объекты Documents. Если метод Save вызывает коллекция, то сохраняются все документы этой коллекции. При этом его синтаксис:

    Save(NoPrompt, OriginalFormat)

    Оба параметра необязательны. Если значение первого - True, Word автоматически сохраняет все документы, в противном случае возникнет диалог с пользователем о сохранении каждого из документов. Параметр OriginalFormat задает формат сохранения так же, как и в методе Close. У метода Save, используемого для сохранения отдельного документа, параметров нет. Если сохраняется новый документ, с которым еще не связано имя файла, его хранящего, будет вызвано диалоговое окно SaveAs, в котором пользователь задаст это имя и, если надо, путь.

    Для получения доступа к элементу коллекции, как обычно, можно вызвать метод Item. Его единственный параметр Index задает порядковый номер или имя документа в коллекции. Item является методом по умолчанию, так что индекс можно непосредственно указывать у объекта, задающего коллекцию.

    Класс Documents имеет типичные для коллекций свойства:

  • Application ;
  • Count ;
  • Creator ;
  • Parent.
  • Эти свойства мы описали, когда речь шла о коллекции WorkBooks. Закончим рассмотрение этой коллекции примером:

    Public Sub WorkWithDocuments()
    'Работа с коллекцией документов
    Dim N As Long, I As Byte
    Dim PathDir As String
    PathDir = "e:\O2000\CD2000\Ch1\"
    With Documents
        N = .Count
        Debug.Print "Число документов в коллекции Documents "  _
        "при открытии приложения Word = ", N
        ' Добавление 2-х новых документов (второй представляет шаблон)
        .Add
        .Add NewTemplate:=True
        'Добавление двух существующих документов
        .Open (PathDir  "DocThree")
        .Open (PathDir  "DocFive")
        N = .Count
        Debug.Print "Число документов после 4-х вызовов методов " _
             "Add и Open =", N
        Debug.Print "Имена документов в коллекции:"
        For I = 1 To .Count
            Debug.Print .Item(I).Name
        Next
        'Закрытие двух документов и, следовательно, удаление их из коллекции
        .Item(2).Close
        .Item(3).Close
        N = .Count
        Debug.Print "Число документов после двух вызовов " _
             "метода Close =", N
        Debug.Print "Имена документов, оставшихся в коллекции:"
        For I = 1 To .Count
            Debug.Print .Item(I).Name
        Next
    End With
    End Sub

    Приведем результаты отладочной печати (В данном примере испульзуюся документы Dex1, DocFive, DocThree:

    Число документов в коллекции Documents при открытии приложения Word =  1               
    Число документов после 4-х вызовов методов Add и Open =  5 
    Имена документов в коллекции:
    DocFive.doc
    DocThree.doc
    Template2
    Document3
    Dex1.dot
    Число документов после двух вызовов метода Close =   3 
    Имена документов, оставшихся в коллекции:
    DocFive.doc
    Template2
    Dex1.dot

    Обратите внимание на то, что элементы добавляются в начало коллекции, а не в ее конец, как это было при добавлении элементов в коллекцию WorkBooks Excel. При удалении элемента происходит перенумерация индексов, поэтому удаляется второй и четвертый элемент коллекции при последовательном выполнении методов Item(2). Close, Item(3).Close.

    Коллекция Paragraphs

    Свойство Paragraphs, возвращающее коллекцию абзацев, имеют объекты класса Documents, Selection, Range. Абзац - это не только последовательность символов, но и структурно выделенная единица текста, характеризуемая параметрами: отступом или выступом по отношению к границам листа документа, межстрочными интервалами, расположением первой строки, стилем и пр. Конечно, все эти характеристики связаны в первую очередь с самим объектом, точнее с классом Paragraph. Но, как это часто бывает в Office 2000, свойства и методы объекта включаются и в коллекцию, содержащую эти объекты. В какой-то мере происходит наследование снизу вверх.

    У коллекции Paragraphs два метода, типичные для всех коллекций: Item и Add. Первый, как всегда, определяет элемент коллекции, заданный параметром Index. Абзацы не имеют имен, и индекс всегда задает порядковый номер элемента. Нумерация абзацев в коллекции начинается с 1. Метод Add используется для добавления нового пустого абзаца. Его синтаксис:

    Add(Range)

    Необязательный параметр Range указывает точку вставки, - абзац вставляется перед той частью текста, которую задает объект Range. Если параметр опущен, абзац вставляется в конец документа или после объекта Selection и Range, если они вызвали метод Add.

    Для вставки пустого абзаца чаще всего применяются методы объектов Range и Selection: InsertParagraph, InsertParagraphAfter, InsertParagraphBefore. Они не имеют параметров. Новый абзац заменяет текст или вставляется после или перед частью текста, заданного объектом Range или Selection, вызвавшего соответствующий метод.

    Предупреждение:

    Осторожнее с методом InsertParagraph: он заменяет весь имеющийся текст новым, пустым абзацем!

    Для вставки текста в созданный пустой (или непустой) абзац могут быть использованы методы объектов Range и Selection: InsertAfter и InsertBefore. Их единственный параметр - Text - задает текст, добавляемый в начало или в конец части текста, заданной объектами Range и Selection, после чего объекты расширяются, дабы включить добавленный текст. Для удаления абзацев может использоваться метод Delete объектов Range и Selection.

    В коллекции Paragraphs много методов, "наследуемых" у объекта Paragraph. Чаще всего они применяются к отдельному абзацу, но иногда вызываются коллекцией, чтобы применить метод ко всем абзацам коллекции. Вот эти методы:

  • OpenUp, CloseUp, OpenOrCloseUp - вставляют или удаляют фиксированное количество пробелов (12) перед абзацем. OpenOrCloseUp - переключатель: если есть пробелы, он их удаляет, нет - вставляет.
  • Indent и Outdent - увеличивают и уменьшают отступ абзаца (или всех абзацев коллекции) от края листа.
  • OutlineDemote, OutlinePromote и OutlineDemoteToBody - понижают и повышают уровень заголовка в интервале Heading1 : Heading8. При понижении последнего уровня -Heading 8 стиль заголовка меняется на стиль Normal.
  • Reset - удаляет форматирование, сделанное вручную, применяя формат, заданный стилем абзаца.
  • Space1, Space2, Space15 устанавливают в абзаце межстрочный интервал: одинарный, двойной или полуторный.
  • TabHangingIndent(Count) и TabIndent(Count) изменяют выступ или отступ абзаца от края листа на заданное количество позиций, определенное параметром Count. Если значение этого параметра положительно, происходит увеличение, иначе - уменьшение отступа (выступа).
  • Коллекция Paragraphs имеет общие свойства Count, Parents, Creator и Application. Кроме того, есть много свойств и методов, специфических для абзацев. Иногда, одной и той же цели можно добиться, вызывая метод или изменяя свойство. За подробностями отсылаем к документации.

    Коллекция Sections

    Свойство Sections, возвращающее коллекцию разделов, имеют объекты класса Documents, Selection, Range. Разделение документа на разделы позволяет придать документу подходящую структуру. Обычно раздел - довольно крупная единица текста в отличие от абзаца. Например, если документ представляет книгу, то каждый ее параграф или глава может быть выделена в отдельный раздел. При установке разделов вручную из меню Insert выбирается пункт Break, позволяющий закончить предыдущий раздел и начать новый. Раздел кончается специальным символом прерывания определенного типа. В зависимости от типа символа прерывания новый раздел может начинаться:

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

    Вернемся к коллекции Sections. Она имеет свойства, уже известные нам по другим коллекциям. Поэтому мы их только перечислим:

    Application, Count, Creator, Parent, First, Last.

    Новым, ранее не упоминавшимся является свойство PageSetup. При обращении к нему возвращается объект класса PageSetup, свойства и методы которого позволяют установить характеристики страницы одновременно для всех разделов коллекции. Метод Item позволяет получить доступ к элементу коллекции. Метод Add позволяет добавить новый раздел в документ:

    Add(Range, Start)

    Возможный параметр Range указывает объект, перед которым будет вставлен символ прерывания, заканчивающий раздел. После символа прерывания будет начинаться новый раздел объектом Range. Если параметр Range опущен, символ прерывания вставляется в конец документа. Возможный параметр Start определяет тип символа прерывания раздела. Он может быть задан одной из констант:

    wdSectionNewPage, wdSectionContinuous, wdSectionEvenPage, wdSectionOddPage, wdSectionNewColumn

    Смысл, задаваемый этими константами, ранее уже был определен. В зависимости от их значения новый раздел будет начинаться со следующей страницы, на той же странице, на четной и нечетной странице. Последняя константа используется при работе с таблицами, позволяя по-разному форматировать каждый из ее столбцов. Если параметр Start опущен, новый раздел будет начинаться со следующей страницы.

    Для удаления раздела из коллекции может быть использован метод Delete объектов Selection и Range.

    Взгляните на пример работы с текстом документа, в котором создаются новые разделы и добавляются абзацы:

    Public Sub WorkWithSecAndPar()
    'Работа с разделами и абзацами
    'Добавление новой книги
    Documents.Add
    Documents(1).Activate
    With ActiveDocument
        'Вставка двух разделов в документ
        'Раздел начнется с нечетной страницы
        .Sections.Add Start:=wdSectionOddPage
        .Sections.Add
        'Вставка абзаца во второй раздел
        .Sections(2).Range.Paragraphs.Add
        .Sections(2).PageSetup.LeftMargin = 3
        .Sections(2).Range.Style = "Heading 1"
        .Sections(2).Range.Font.Name = "Arial"
        .Sections(2).Range.Paragraphs(1).Range.InsertBefore ("Лекция 1")
        'Вставка нового раздела и абзаца
        .Sections.Add Start:=wdSectionNewPage
        .Sections.Last.Range.Paragraphs.Last.Range.InsertBefore ("Параграф 1")
        .Sections.Last.Range.Paragraphs.Add
        'Вставка нового раздела и абзаца
        .Sections.Add Start:=wdSectionNewPage
        .Sections.Last.Range.Paragraphs.Last.Range.InsertBefore ("Параграф 2")
        .Sections.Last.Range.Paragraphs.Add
        'Вставка нового раздела в конец документа
        'Раздел начнется с нечетной страницы
        .Sections.Add Start:=wdSectionOddPage
        .Sections.Last.PageSetup.LeftMargin = 23
        .Sections.Last.Range.Font.Name = "TimesNewRoman"
        'Вставка абзаца
        .Sections.Last.Range.Paragraphs(1).Range.InsertBefore ("Лекция 2")
        .Sections.Last.Range.Paragraphs.Add
        Debug.Print "Число разделов документа =", .Sections.Count
        Debug.Print "Число абзацев документа =", .Paragraphs.Count
        'Удаление раздела выполняет метод объекта Range
        .Sections(1).Range.Delete
        Debug.Print "Число разделов документа =", .Sections.Count
    End With
    
    End Sub

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

    Sections.Last.Range.Paragraphs(1).Range.InsertBefore ("Лекция 2")
  • Свойство Sections активного документа возвращает объект Sections, задающий коллекцию разделов этого документа.
  • Свойство Last объекта возвращает объект Section, задающий последний раздел в этой коллекции.
  • Свойство Range возвращает объект Range, связанный с данным разделом. Теперь становятся доступны методы и свойства объекта, в частности свойство Paragraphs, которым объект Section не обладает.
  • Вызов Paragraphs(1) возвращает объект класса Paragraph, задающий первый абзац из коллекции абзацев данного раздела. Заметьте: опущен метод по умолчанию Item, так что запись Paragraphs(1) является краткой формой записи Paragraphs. Item (1)
  • И снова мы получаем объект Range, теперь уже связанный с абзацем.
  • На последнем шаге вызывается метод InsertBefore объекта Range, позволяющий добавить в начало абзаца текст, заданный аргументом метода. В нашем случае - лекция 2.
  • Коллекции Characters, Words, Sentences

    Свойства Characters, Words, Sentences возвращающие коллекции символов, слов или предложений, имеют объекты класса Documents, Selection, Range. Все эти коллекции устроены довольно просто. Они имеют известные нам свойства:

    Application, Count, Creator, First, Last, Parent

    и единственный метод Item(Index). Этот метод для всех коллекций возвращает объект Range, позволяющий работать как с единственным символом, так и с совокупностью символов, соответствующей слову или предложению. Добавление в коллекцию и удаление из нее элементов осуществляется методами объекта Range.

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

    Коллекции и конструкция For Each … Next

    При работе с коллекциями довольно часто приходится организовывать цикл по всем элементам коллекции. До сих пор во всех наших примерах мы использовали обычные средства - цикл " For ", где количество шагов цикла определялось свойством Count (его имеет каждая коллекция). Наша конструкция выглядела так:

    With <объект>
    	For i = 1 To .Count
    	.Item(i) 	' Доступ к i-му объекту и работа с ним
    	Next i
    End With

    VBA предлагает специальную конструкцию " For Each " для организации подобных циклов. Синтаксис конструкции таков:

    For Each <Элемент> In <Группа>
    [<Операторы>]
    [Exit For]
    [<Операторы>]
    Next [<Элемент>]

    где:

    <Группа> - имя объекта-коллекции или массива.

    <Элемент> - объект (переменная), совпадающий по классу с элементами коллекции, или имеющий тип Variant. Для массивов допустим только тип Variant. Нормально цикл заканчивается, когда переменная цикла получила все возможные значения и коллекция исчерпана. Но можно организовать досрочный выход. Для этого используется внутренняя конструкция Exit For. Обычно она помещается в Then -ветвь оператора If. Если условие выхода выполняется, следом выполняются Exit For и следующие за ним операторы, требуемые для корректного завершения цикла. После чего управление покидает цикл.

    Цикл For Each не может использоваться для массивов с элементами, определенными пользователем. Последнее объясняется тем, что переменная типа Variant не может принимать пользовательский тип.

    Приведем пример использования "старой" и "новой" конструкций:

    With Documents
    	For i = 1 To .Count		For Each doc In Documents
    		Debug.Print 	.Item(i)		Debug.Print 	doc
    	Next i 				Next doc
    End With

    Преимущество "новой" очевидно: удобнее иметь сам элемент doc вместо индекса элемента i. Особенно это может быть важно, когда в ходе цикла приходится многократно обращаться к элементу doc.

    При работе с коллекциями используйте, как правило, конструкцию For Each. Кроме всего прочего, она выполняется намного эффективнее по времени исполнения.

    Объекты Range

    Роль коллекций во всех приложениях Office 2000 велика. Если одновременно могут существовать несколько объектов (экземпляров) одного и того же класса, то существует и объединяющий их класс - коллекция, в которой собраны все экземпляры. Класс коллекция позволяет работать с последовательностью элементов - экземпляров класса.

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

    Что определяет объект Range?

    Пусть задана коллекция элементов - последовательность индексированных элементов. Индексы (ключи) элементов задают порядок их расположения в коллекции. Индексы могут быть как числами, так и именами. Объект Range позволяет задать произвольный диапазон этой последовательности, для чего достаточно задать индексы первого и последнего элемента. Диапазон может быть стянут в точку, так что объект Range может определять единственный элемент, а в приложении Word и пустой элемент - точку вставки. Используя свойства и методы объекта Range, можно выполнять групповые операции над всеми элементами диапазона. В одном из предыдущих примеров встречаются строки, использующие объект Range в Excel:

    xlApp.Range("A1:A2") = 2
    xlApp.Range("B1") = "=A1+A2"
    xlApp.Range("B2") = "=A1*A2"

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

    Метод Range

    Ранее мы говорили, что объект класса Paragraph имеет свойство Range, иначе говоря, в него вложен объект Range., задающий последовательность символов данного абзаца. Объектов, имеющих свойство Range, немало. Это понятно, ведь не только с абзацами полезно связать диапазон, соответствующий объекту. При обращении к свойству Range таких объектов в качестве результата получаем соответствующий диапазон - ссылку на объект Range.

    В ряде случаев можно определить новый объект класса Range, используя метод Range. Заметьте: метод, а не свойство. Так объекты более высокой иерархии, например объект класса Document, имеют метод Range и не имеют соответствующего свойства. Синтаксис метода таков:

    Function Range(Start, End) As Range

    Он имеет два параметра: Start и End - и возвращает как результат объект класса Range.

    Если объект Range уже построен, то значения его параметров Start и End можно переопределить, вызвав его метод SetRange, в котором можно задать новые значения этих параметров.

    В следующем примере работы с документом Word демонстрируется как применение свойства Range, так и метода Range. В нем же показано и применение метода SetRange.

    Public Sub WorkWithRange()
    Dim myr As Range, myr1 As Range
    Dim i As Byte
    'Добавляем новый документ
    Documents.Add
    With ActiveDocument
    'Добавляем 7 абзацев в текст созданного документа
        For i = 1 To 7
            .Paragraphs.Last.Range.Text = "Абзац "  i
            .Paragraphs.Add
        Next i
    'Используется свойство Range
        Set myr = .Paragraphs(1).Range
    'Выделен первый абзац
        myr.Select
    'Новый объект myr1 задает пустой объект - позицию курсора
    'В правой части вызывается метод Range
        Set myr1 = ActiveDocument.Range(Start:=myr.Start, End:=myr.Start)
        myr1.Select
    'Теперь объект myr1 задает единственный символ -первый символ текста
    'Здеесь использован метод SetRange
        myr1.SetRange Start:=myr1.Start, End:=myr1.End + 1
        myr1.Select
    'Три абзаца с третьего по пятый выделяются курсивом
        myr1.SetRange Start:=.Paragraphs(3).Range.Start, End:=.Paragraphs(5).Range.End
        myr1.Font.Italic = True
        myr1.Select
    End With
    End Sub

    Объекты Selection

    Еще один общеупотребительный объект - Selection. Как и Range, этот объект присутствует в большинстве приложений Office 2000. Он задает выделенную область документа Word, рабочего листа Excel, область в окне презентации. Его особенность в том, что в каждом окне (точнее, в каждом подокне) может существовать только один объект Selection. Каждое новое выделение некоторой области в подокне отменяет или модифицирует старое. Этим он отличается от объектов Range, несколько экземпляров которых могут существовать одновременно. Selection, как и объект Range, задает непрерывную область элементов. Но есть и принципиальное отличие: объект Selection не является диапазоном, заданным своим началом и концом, - это некоторая область, например таблица или ее столбец.

    Но объекты Selection и Range имеют и много общего. Прежде всего, оба предназначены для того, чтобы задавать некоторую область элементов, и позволяют выполнять действия над элементами этой области. Возможности этих объектов для работы с элементами области примерно одинаковы. Так, у приложения Word свойства и методы данных классов объектов совпадают на 90%. Вот почему почти каждую задачу, которую можно решить в терминах объекта Selection, можно решить и в терминах объекта Range. Macrorecorder (о нем еще будет подробный разговор) любит использовать объект Selection в своей работе, и очень часто программист "подправляет" программу, переписывая ее для повышения эффективности в терминах свойств и методов объекта Range.

    Отметим еще одну связь (ее можно назвать двойственностью) между этой парой объектов. У объекта Range есть метод Select, который выделяет заданный диапазон, создавая объект Selection, после чего можно использовать свойства и методы этого объекта. Также и объект Selection имеет метод Range, который определяет диапазон, связанный с областью выделения, после чего можно работать с этим диапазоном, используя свойства и методы объекта Range. Перепишем наш пример, где использовался объект Range, задействовав объект Selection:

    Public Sub WorkWithSelection()
    Dim myr As Range
    Dim i As Byte
    'Добавляем новый документ
    Documents.Add
    With ActiveDocument
    'Добавляем 7 абзацев в текст созданного документа
        For i = 1 To 7
            .Paragraphs.Last.Range.Text = "Абзац "  i
            .Paragraphs.Add
        Next i
    'Используется свойство Range
        Set myr = .Paragraphs(1).Range
    'Выделен первый абзац. Создаем объект Selection
        myr.Select
    'Действия с объектом Selection
    'Стягивание в начало абзаца - точку вставки
        Selection.MoveLeft
    'Расширение на один абзац вправо, снова выделяя первый абзац
        Selection.MoveDown Unit:=wdParagraph, Count:=1, Extend:=wdExtend
    'Передвинемся к началу третьего абзаца
        Selection.Move Unit:=wdParagraph, Count:=2
    'Три абзаца с третьего по пятый выделяются курсивом
        Selection.MoveDown Unit:=wdParagraph, Count:=3, Extend:=wdExtend
        Selection.Font.Italic = True
    End With
    End Sub

    Первоначально объект Selection создается как результат вызова метода Select объекта Range. После этого можно работать с этим объектом. При изменении диапазона объекта Selection приходится работать не с параметрами Start и End, как это делается для объектов Range, а использовать специальные методы Move, часть из которых мы применили в нашем примере. Вот их краткое описание:

  • метод MoveLeft сжимает область выделения до точки и передвигает ее в начало диапазона. В примере точка вставки перемещается к началу первого абзаца;
  • метод Move сжимает область выделения до точки и передвигает ее в нужное место. В примере точка вставки перемещается на два абзаца;
  • метод MoveDown расширяет область выделения. Параметр Unit указывает единицы, в которых ведется отсчет при расширении области (у нас - в абзацах); параметр Count задает число этих единиц. Параметр Extend указывает, нужно ли расширение или перемещение области, сжатой в точку вставки.
  • Метод Select и свойство Selection

    Рассматривая в приложении Word объект Range, мы видели, что он может быть получен как результат вызова метода Range объектов одних классов и свойства Range объектов других классов. Свойством Range обладают объекты более низких уровней иерархии - коллекции слов и ячеек, абзацы и строки. Считается, что в каждый такой объект вложен объект Range, задающий диапазон, связанный с объектом. При вызове свойства этот существующий объект возвращается, и с ним можно работать. У объектов верхнего уровня иерархии: Application, Windows - встроенного диапазона нет, но зато есть метод Range, позволяющий создать новый объект этого класса.

    С объектом Selection ситуация аналогична. И здесь свойство Selection возвращает уже существующий объект, а метод Select позволяет создать новый объект. Но здесь ситуация двойственна - объекты, имеющие свойство Range, обладают методом Select и, наоборот, объекты верхнего уровня иерархии имеют свойство Selection. Объяснение очевидно: объект Selection существует в единственном экземпляре в каждом подокне, и поэтому объекты более низких уровней иерархии просто не могут иметь встроенное свойство Selection. Им могут обладать только объекты класса Pane (подокно), Windows и Application.

    Рассмотрим синтаксис метода Select:

  • Sub Select()
  • Sub Select([Replace])
  • В первом случае создается новая область выделения - объект Selection, во втором - область выделения можно расширить или заменить в зависимости от значения параметра Replace. Заметьте: метод Select реализован не как функция, явно возвращающая результат, а как процедура ( Sub ), которая объекта Selection не возвращает. Создание этого объекта - результат побочного эффекта этой процедуры. Созданный объект связывается с объектами верхнего уровня иерархии: окном и приложением. Его можно получить, обратившись к глобальному свойству Selection. Но Вы не можете получить ссылку на этот объект, а, следовательно, не можете создать переменную этого класса, так, как это могли делать при работе с объектами класса Range (вспомните переменную MyRange из наших примеров). Это предохраняет нас от соблазна "обмануть систему" и иметь две переменные - два объекта Selection одновременно.

    Типичный и правильный способ работы с объектом Selection таков:

  • Создается или выбирается объект, область которого должна быть выделена.
  • Для этого объекта вызывается метод Select, возвращающий в качестве результата объект Selection.
  • Проводится работа с объектом Selection в области выделения.
  • Если нужно перейти к новой области выделения, то либо область выделения перемещается (как в нашем примере), либо повторяются действия, начиная с первого пункта.
  • Рассмотрим пример, в котором пользователь переключается между двумя областями выделения

    Sub WorkWithTwoReg()
    'Переключение между двумя областями выделения документа
    'Создание двух областей
    Dim myRange1 As Range
    Dim myRange2 As Range
    Dim i As Byte
    Dim Answer As Variant ' Выбор пользователя
    'Добавляем новый документ
    Documents.Add
    With ActiveDocument
    'Добавляем 7 абзацев в текст созданного документа
        For i = 1 To 7
            .Paragraphs.Last.Range.Text = "Абзац "  i
            .Paragraphs.Add
        Next i
        Set myRange1 = .Range(Start:=.Paragraphs(2).Range.Start, _
            End:=.Paragraphs(3).Range.End)
        
        Set myRange2 = .Range(Start:=.Paragraphs(6).Range.Start, _
            End:=.Paragraphs(7).Range.End)
        Answer = InputBox(prompt:=" Выберите область выделения (1/2)", _
                Default:=1)
        If Answer = 1 Then
            myRange1.Select
            'Макрос ItInSel работает с первой выделенной областью
            ItInSel
        Else
            myRange2.Select
            'Макрос ItInSel работает со второй выделенной областью
            ItInSel
        End If
    End With
    
    End Sub

    В этом макросе почти все применяемые средства хорошо знакомы. До сих пор мы не пользовались только стандартным для Visual Basic методом InputBox, который открывает диалоговое окно, позволяющее принять ввод пользователя. Заметьте, что работу в выделенной области осуществляет процедура ItInSel. Ее можно было сделать довольно сложной, но мы ограничились одним оператором:

    Public Sub ItInSel()
    Selection.Font.Italic = True
    End Sub

    Анализируя этот макрос, обратите внимание на два обстоятельства:

  • Если мы хотим постоянно работать с некоторыми областями, имеет смысл создать соответствующие им объекты. "Хранителями" областей выступают объекты класса Range В нашем примере это переменные myRange1 и myRange2. Объекты Selection появляются в последнюю минуту, когда область нужно выделить и начать с ней работать.
  • Работа с объектом Selection может быть предпочтительнее, так как явные ссылки заменяются косвенными. Это позволяет создать процедуру, не зависимую от области. Подобную ситуацию демонстрирует вызов процедуры ItInSel.
  • Активные объекты и метод Activate

    Объект Selection является примером косвенной адресации. Он задает некоторую выделенную область, и его свойства и методы позволяют изменять состояние этой области. Другой пример косвенной адресации - активные элементы. Как в подокне может быть только один выделенный элемент, так и активный элемент может быть единственным в своем классе - одно активное окно, один активный документ или рабочий лист. Обычно активный элемент находится в фокусе клавиатуры, именно ему направлен ввод пользователя. Сделав активным новый элемент, мы отменяем, деактивируем элемент, ранее находившийся в фокусе клавиатуры.

    Метод Activate делает активным элемент, его вызвавший. Этим методом обладают элементы верхних уровней иерархии: Application, Window, Pane, Document, WorkBook, Worksheet, Chart и др. В приложениях Word и PowerPoint эти объекты обладают также булевым свойством Active, имеющим статус "только для чтения". При активизации объекта свойство Active получает значение True, при деактивации - False. Значение свойства позволяет понять, в каком состоянии находится тот или иной объект этих приложений.

    Чтобы обратиться к выделенному объекту, достаточно иметь одно глобальное свойство Selection, поскольку в каждый текущий момент существует только один выделенный элемент. Активных элементов одновременно существует несколько, по одному в каждом классе. Поэтому для обращения к активному элементу надо указывать его класс. Поэтому для каждого класса имеется свое глобальное свойство. Чтобы обратиться к активному элементу некоторого класса Z, нужно вызвать соответствующее глобальное свойство ActiveZ, например ActiveDocument или ActiveWindow. В наших примерах мы неоднократно уже использовали обращение к активному документу - ActiveDocument. Рассмотрим еще один пример, в котором пользователь в приложении Excel выбирает рабочий лист. В зависимости от его выбора активизируется указанный лист, и в двух первых ячейках появляется приветствие, текст которого также зависит от выбора пользователя:

    Public Sub Actis()
    Dim Answer As Integer
    Answer = InputBox(Prompt:="Выберите номер страницы для Вашей работы(1/2/3)", _ Default:=1)
    'Активизирует рабочий лист, выбранный пользователем
    ActiveWorkbook.Sheets(Answer).Activate
    'Работа с активным листом
    ActiveSheet.Cells(1, 1) = "Привет,"
    Select Case Answer
    Case 1: ActiveSheet.Cells(1, 2) = "Михаил!"
    Case 2: ActiveSheet.Cells(1, 2) = "Владимир!"
    Case Else: ActiveSheet.Cells(1, 2) = "Люди!"
    End Select
    End Sub

    На этом мы заканчиваем первое знакомство с общеупотребительными объектами Office 2000. В заключение мы хотим рассказать уже не о каких-либо конкретных объектах, а об удивительном программном средстве, позволяющем работать с ними. Речь пойдет о Macrorecorder.

    Macrorecorder

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

    Так возникает двойственность. Одни и те же вещи можно сделать и визуально, и программно - эффект будет один. Большинство приложений Office 2000, и в первую очередь Word и Excel, рассчитаны на визуальный способ работы с ними. Но программистов не обманешь - они-то знают, что всякий раз, когда пользователь визуально инициирует действие, вызывается программа, выполняющая это действие. Дело в том, что система следит за действиями пользователя, анализирует их и запускает программы, соответствующие этим действиям. Иначе говоря, происходит трансляция с языка действий в язык программирования. Поскольку этот язык объектный, то можно говорить, что действия пользователя (события) интерпретируются и приводят к вызову методов и изменению свойств в мире объектов. Поскольку есть интепретатор действий, то можно построить и транслятор.

    Macrorecorder - это и есть транслятор. Всякий раз, когда пользователь запускает Macrorecorder, создается программа (макрос) на языке VBA, которая является результатом трансляции действий пользователя с момента запуска Macrorecorder до момента окончания записи макроса. Пользователь оперирует с образами объектов на экране, программа - с объектами Office 2000. Заметьте: одного и того же эффекта, пользователь иногда может достичь разными путями - он может вызвать команду меню или щелкнуть соответствующую кнопку или нажать комбинацию "горячих" клавиш. С этими разными событиями может связываться одна и та же процедура обработки. Поэтому созданная Macrorecorder программа в таких случаях будет одинаковой, не зависящей от того, как пользователь добился нужного ему эффекта.

    На сегодня Macrorecorder не очень "интеллектуален" - он слепо копирует действия пользователя и не занимается оптимизацией созданной им программы. Так, если пользователь записал в ячейку А1 число 15, в А2 - 17, а потом передумал и решил вернуться к ячейке А1 и заменить 15 на 21, то Macrorecorder в программе повторит все его действия. "Любимый" объект Macrorecorder - Selection, и это понятно: всякий раз, когда пользователь выбирает новый объект, Macrorecorder создает новый объект Selection. Сегодня типична ситуация, когда программист использует макрос, созданный Macrorecorder, как заготовку, оптимизируя код вручную. Думается, интеллект Macrorecorder повысится в следующих версиях. Но и сейчас это крайне полезное средство. Office 2000 позволяет чрезвычайно просто решить вручную массу задач (в этом вся его суть). Вместе с тем необходимость в решении таких задач может возникать неоднократно, и потому полезно иметь соответствующую программу. Так что технология такова: один раз задача решается вручную, Macrorecorder создает макрос, транслируя наши действия, затем макрос, если надо, оптимизируется и запускается всякий раз, когда возникает необходимость решения данной задачи.

    Завершим описание примером. Наиболее удобен для демонстрации Excel, - именно здесь вручную можно решать очень необычные задачи. Поэтому и Macrorecorder интенсивнее всего используется в Excel. Хотя, привыкнув, Вы будете применять его и в других приложениях Office 2000. Рассмотрим написание в Excel программы, создающей последовательность первых N чисел Фибоначчи, - типичная задача для студентов первого курса, изучающих программирование. В ней есть рекуррентные соотношения, цикл, она требует понимания понятия "переменная". Рекуррентные соотношения для получения чисел Фибоначчи таковы:

    A1 = 1;	A2 = 2;		A k= A k-1 + A k-2; 	k = 3…N;
    (рис 1.11)

    Вот как мы решали эту задачу вручную ( рис. 1.11). Вначале вызвали Macrorecorder, выбрав в меню Tools пункт Macro, затем - Record New Macro (проще щелкнуть кнопку начала записи макроса, если она есть на панели). В появившемся диалоговом окне задали имя макроса - Fibonachi. Заметьте: появляется кнопка окончания записи макроса, если ее не было на соответствующей панели. Теперь наши дальнейшие действия будут транслироваться в соответствующую программу. В ячейку А1 мы записали текст " Числа Фибоначчи ", в ячейки А2 и А3 - числа 1 и 2, в ячейку А4 - формулу " = А2+А3 ", а затем скопировали эту формулу до ячейки А20 включительно. По ходу копирования формула пересчитывалась, и в ячейках появлялись значения, соответствующих чисел Фибоначчи. Затем мы, щелкнув кнопку, выключили запись макроса. Результаты действий - на рис. 1.7. Созданный Macrorecorder макрос Fibonachi теперь доступен, и его можно вызывать в любой момент. Вот его текст:

    Sub Fibonachi()
    '
    ' Fibonachi Macro
    ' Macro recorded 28.02.1999 by Vladimir Billig
    
        Selection.Font.Bold = True
        ActiveCell.FormulaR1C1 = "Числа Фибоначчи"
        Range("A2").Select
        ActiveCell.FormulaR1C1 = "1"
        Range("A3").Select
        ActiveCell.FormulaR1C1 = "2"
        Range("A4").Select
        ActiveCell.FormulaR1C1 = "=R[-2]C+R[-1]C"
        Selection.AutoFill Destination:=Range("A4:A20"), Type:=xlFillDefault
        Range("A4:A20").Select
    End Sub

    В созданном макросе используются уже известные нам объекты: Range, Selection, ActiveCell и метод Select объекта Range. В комментариях нуждается свойство ячеек Excel - FormulaR1C1, - позволяющее связать с ячейкой значение или формулу (для ячейки А4 ), заданную в относительных координатах R ( Row - строка) и C ( Column - столбец). Отсчет координат ведется от активной ячейки, поэтому для ячейки А4 формула " =А2 +А3 " в этих координатах принимает вид: " =R[-2]C+R[-1]C ". Основная операция копирования не потребовала организации цикла в программе. Этот цикл реализован внутри метода AutoFill, вызванного для объекта Selection. Два параметра этого метода Destination и Type задают область и тип копирования. В оптимизации этот макрос не нуждается

    Ранее мы говорили, что браузер объектов - это Ваш неизменный спутник и помощник в процессе программистской работы. Другим таким же полезным помощником является Macrorecoder!

    Дело даже не в том, чтобы получить макрос для многократного использования, - Вы и сами его можете написать. Но часто возникает ситуация, когда Macrorecoder запускается для того, чтобы понять, какие объекты и какие методы следует использовать для решения той или иной задачи. Например, Вы могли бы не знать, как скопировать формулу в соседние ячейки, чтобы она корректно изменилась при копировании. Макрос Fibonachi подсказал бы Вам, что для этого следует использовать метод AutoFill. Заодно Вы бы поняли, что в область копирования ( destination ) должен быть включен и источник копирования. Так что не забывайте Macrorecoder - это Ваше подручное средство.

    На этом мы заканчиваем предварительное знакомство с объектами Office 2000 и переходим к систематическому изучению самого языка программирования VBA.

    Страницы:

    Программный код большинства примеров данной лекции можно найти в проектах, доступных для просмотра: BookOne, BookThree, BookFive, Dex1, DocFive, DocThree.

    VBA и объекты. Обзор

    В этой книге основное внимание мы хотим уделить самому языку VBA - его ядру, средствам, определяющим этот язык, как обычный язык программирования. Но заранее можно предсказать, что "столкновения" или лучше сказать встречи с объектами нам не избежать. Все-таки, сутью VBA является его возможность непосредственной работы с объектами. Поэтому эту лекцию мы решили посвятить первому знакомству с объектами. Подробное их рассмотрение будет предметом следующей книги.

    Office - это среда, в которой многие задачи можно решать без всякого программирования. Office 2000 - это среда, в которой класс таких задач существенно расширился. Но для программиста ценность офисной среды состоит в том, что все задачи, решение которых может быть получено "руками", можно получить и программно. И все, что нельзя сделать руками, можно сделать программно. Для программирования используется язык VBA (Visual Basic for Applications), представляющий расширение ядра языка VB (Visual Basic) объектами, определяющими приложения Office 2000.

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

  • В работе участвуют специалисты в проблемной области и программисты. Целью работы является создание системы "живых" документов офиса или предприятия. Работа строится на мощной основе, которую составляют документы, предоставляемые средой Office 2000. Документами могут быть бланки, отчеты, справки, базы данных, запросы к ним, графики, диаграммы. Документы мы называем живыми, поскольку в процессе работы конечных пользователей (специалистов) они могут изменяться. Эти изменения являются результатом выполнения различных функций над данными, размещенными в документах.
  • Библиотека объектов Office 2000 представляет собой каркас документов (чуть позже мы определим более точно этот термин). Открывая впервые одно из приложений Office 2000, например Word, специалист получает готовый каркас некоторого документа, - для Word это документ, в котором основным типом данных будут тексты. Затем специалист берется за дело и наполняет этот каркас плотью и кровью, создавая уже реальный документ, входящий в общую систему. Однако, как бы ни увеличивались стандартные возможности среды, всегда для оживления документа чего-нибудь да не хватает, (вспомните, мечту о дефиците одного из героев Райкина). И тогда приходит время программиста.
  • В процессе создания "живых" документов программист будет работать на VBA, едином языке программирования, объединяющем мир объектов среды Office 2000. VBA представляет мощный, универсальный язык программирования и на нем можно делать все, или почти все, что и на любом другом языке программирования. Но главное его достоинство состоит в том, что в нем определены и доступны для программиста все объекты Office 2000. Это значит, что доступны все документы, все их части, и части этих частей, вплоть до символа, рисунка, ячейки. Это и позволяет программисту легко проводить настройку системы документов с учетом их специфики. (В английском языке для этой деятельности есть хороший термин - customization, но, может быть, и термин "настройка" не хуже).
  • Ранее уже говорилось, о том, что такой стиль работы становится популярным. Язык VBA является теперь отчуждаемым от среды Office 2000, он может быть встроен в любую другую среду. Реально этот процесс уже идет, мы приводили пример с программными продуктами фирмы Corel, но есть и большое число других подобных примеров.

    Библиотека объектов Office 2000 - каркас приложений

    В тех книгах, которые мы написали последнее время по Visual C++ и по Офисному программированию, большая часть достаточно солидного введения посвящалась основам объектно-ориентированного программирования. Мы полагаем, что каждый программист должен владеть этим аппаратом, поскольку без четкого осознания таких понятий, как класс, интерфейс класса, полиморфизм, наследование, встраивание, невозможно проектирование и разработка сколь либо серьезной системы документов. В этой книге мы не будем останавливаться на этих понятиях, полагая, что читатели с ними знакомы, если же нет, то можно порекомендовать обратиться к нашим книгам по Visual C++ и Офисному программированию, или к любым другим, где эти вопросы хорошо изложены.

    Но на одном термине стоит все-таки остановиться подробнее. Речь пойдет о понимании совокупности библиотек классов, как каркаса приложений (каркаса документов). Когда программист вводит собственный класс объектов, то чаще всего он рассматривает его, как специфический тип данных, расширяющий возможности типов данных, встроенных в язык. Первые библиотеки классов, предоставляемые системой программисту, по существу, представляли расширенный набор типов данных. Но затем стало понятным, что объектный подход может быть полезным и при построении самого приложения. Само приложение стало рассматриваться, как совокупность объектов со своими свойствами, методами и событиями. Более того, стало ясно, что можно строить приложения различной архитектуры и стандартных скелетов приложений не так уже и много. При работе в среде Visual C++ , например, классической является архитектура Документ - Облик (Document -View).

    В современных программных средах большую часть классов, входящих в библиотеку (совокупность библиотек), составляют классы, предназначенные для построения самого приложения, его основы или каркаса. В соответствии с этим такие библиотеки называются каркасом приложений (FrameWork Applications). Такую роль играют библиотеки Visual C++, Delphi и других программных сред.

    Как же обстоит дело в Office 2000? Для программиста Office 2000 - это ничто иное, как обычная совокупность библиотек классов. И так же, как и для других программных сред, их классы представляют собой каркас приложений, или, что может быть точнее с содержательной точки зрения, - каркас документов.

    Дело в том, что изменились цели программиста, работающего в среде Office 2000. Ранее целью программиста было создание приложения, понимаемого как программа, программный проект. Теперь программист является одним из участников (возможно единственным) создания системы документов. Документ, а не программа, становится целью разработки. Программный проект - это лишь часть документа. В Office 2000 программный проект неразрывно связан с документом, хранится, как часть документа, и не может существовать независимо от него. Отсюда становится понятным, что и библиотека классов Office 2000 содержит каркасы основных документов - текстовых документов, документов, основу которых составляют электронные таблицы, презентации, базы данных. Всякий раз, когда создается новый документ, его каркас составляют объекты библиотек, отобранных для построения этого конкретного каркаса документа.

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

    Встраивание вместо наследования

    Обычно, классы, входящие в библиотеку, связаны между собой. Типично, на классах вводится отношение наследования, так что в иерархически связанном семействе классов есть родительские классы и классы - потомки. Наследование - мощный и естественный механизм порождения новых классов. Прародитель семейства может задавать некоторые общие, наиболее фундаментальные свойства и поведение объектов этого семейства, а его многочисленные потомки задают то или иное специализированное поведение. Кроме того, отметим, что наследование позволяет модифицировать поведение объектов - потомков, не меняя поведения объектов исходного родительского класса. Это важный принцип - "не разрушай то, что создано ранее". Ценность такого подхода, в частности, состоит и в том, что каркас конкретного приложения составляют классы - потомки, чьи родители находятся в библиотеке. Поэтому можно добавлять новые свойства, изменять и добавлять новое поведение у приложения, - все это никак не сказывается на родительских классах, хранящихся в библиотеке.

    Наследование, конечно же, не единственно возможное отношение между классами. Программистам хорошо известно встраивание - еще один способ построения нового класса, использующий ранее созданные классы. Пусть построен класс А, тогда при определении нового класса В его элементами - переменными (свойствами класса В ) могут быть объекты класса А. В этом случае говорят, что объекты класса А встроены (вложены) в класс В. Встраивание, как и наследование, - транзитивное отношение. Реально это означает, что возможна сколь угодно высокая степень вложенности объектов. Следует отличать непосредственную вложенность от вложенности уровня n. Так, в новый класс С можно встроить объект класса В, и он будет непосредственно вложен в класс С, а объект класса А, встроенный в объект В, будет иметь уровень вложенности 2 по отношению к классу С.

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

    Class Mother
    {
    	'Раздел атрибутов
    	Chromosome XX;
    'Другие объявления свойств и методов
    ....
    }
    Class Father
    {
    	'Раздел атрибутов
    	Chromosome XY;
    'Другие объявления свойств и методов
    ....
    }

    В классы Mother и Father встроены объекты XX и XY ранее определенного класса Chromosome. Используя множественное наследование, можно создать новый класс, наследующий свойства и поведение его родителей:

    Class Child : Parents Mother, Father
    {
    	'Наследует свойства XX, XY и другие свойства и методы своих родителей
    	'Раздел атрибутов
    	String 	NewProperty;
    	'Другие новые свойства и методы
    }

    Рассмотрим теперь создание класса, основанное на встраивании объектов:

    Class MyChild
    {
    	'Раздел атрибутов
    	Father	F;
    	Mother	M;
    	String	NewProperty;
    	'Другие новые свойства и методы
    }

    Вот объявление объектов этих классов:

    Child 	Son;
    MyChild	Daughter;

    Объекты Son и Daughter обладают одинаковыми свойствами и поведением. И в этом случае мы будем говорить, что классы Child и MyChild подобны. Есть некоторая синтаксическая разница - у объекта Son свойства XX и XY доступны непосредственно, а у объекта Daughter они доступны через вложенные объекты F и M, так что в первом случае мы пишем Son.XX и Son.XY, а во втором - Daughter.F.XY и Daughter.M.XX.

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

    Если происходит переопределение родительских методов в производном классе, то в общем случае, используя встраивание, нельзя построить класс, подобный наследуемому. В нашем примере с классами Child и MyChild встраивание используется при построении класса MyChild как альтернатива наследованию. С другой стороны, в этих классах применяется, и "обычное" встраивание. Заметьте: свойства XX и XY в классах Child и MyChild - это встроенные объекты ранее определенного класса Chromosome. Так что этим примером мы демонстрируем обе ипостаси встраивания.

    Мы так подробно остановились на встраивании по одной простой причине: этот механизм лежит в основе объектной модели в Office 97 и Office 2000. Здесь нет наследования в истинном смысле этого слова, и хотя этот термин иногда и используется, но фактически всегда речь идет лишь о встраивании. Все приложения Office 2000 с объектной точки зрения построены одинаково. Всегда существует задающий приложение корневой объект Application ( Word.Application, Excel.Application и т. д.), в который встроены все остальные объекты данного приложения.

    Когда в объект Application вложен объект X, говорят, что у объекта Application есть свойство X, и запись Application.X означает обращение к объекту X. Сам объект X может быть не менее сложен: в него могут быть встроены другие объекты, например объект Y, а в него в свою очередь - объект Z. Эта цепочка вложенности может быть продолжена. Для приложений Office 2000 типична ситуация, при которой нужно указать 6-7 уровней вложенности, чтобы добраться до объекта, свойство или метод которого будет использовано. Вложенный объект, который является свойством объекта, его содержащего, называют иногда участником (accessor).

    Длинные цепочки, возникающие при именовании объектов, являлись бы большим недостатком, если бы их пришлось выписывать вручную. Но вот пример того, как недостатки можно обращать в достоинства. Частью, используемой в Office 2000 всюду, где можно, технологии интеллектуальной поддержки (intellisense) является поддержка автоматического выписывания длинных имен. Как только после имени объекта ставится точка, автоматически раскрывается список с перечислением всех свойств этого объекта, так что остается только выбрать имя из списка, поставить точку и продолжить этот процесс. Если, поставив точку, Вы не видите списка, то это значит, что-то сделано неправильно, например, не задан класс объекта в операторе объявления или неверно понимается его структура, в любом случае это сигнал, заставляющий задуматься.

    Подводя итог, отметим, что для программиста большинство библиотек Office 2000 задают совокупность "толстых" объектов - объектов Application. В каждый такой корневой объект вложены другие объекты, устроенные не менее сложно. С методами, свойствами и событиями, происходящими в мире этих объектов, и работает программист.

    В заключение взгляните, как я представляю себе "толстый" объект Application.

    (рис 1.1) Вложенность объектов

    Построение каркаса документа

    Мы уже сказали, что совокупность библиотек классов Office 2000 представляет каркас документов, которые могут порождаться в этой программной среде. Давайте же рассмотрим, как создается каркас одного документа. Обычно, это тривиальная операция, выполняемая почти автоматически. В свое время, рассматривая программирование в среде Office 97, мы не считали необходимым введения самого термина "каркас документа". В Office 2000 возросли возможности создания разнообразных каркасов, потому стоит ввести и сам термин и обратить на это особое внимание.

    Итак, всякий раз, когда открывается новый документ в одном из приложений Office 2000, например Word, Excel или Power Point , автоматически создается каркас этого документа. Это означает, что из всей совокупности библиотек выбираются те библиотеки, которые и будут составлять каркас этого документа. И это означает, что все объекты, классы которых определены в этих библиотеках, будут доступны в данном документе.

    Какие же библиотеки входят в каркас документа по умолчанию? Определяющую роль играет то, в каком приложении Вы создаете документ. В каркас всегда входит библиотека, задающая это приложение, - Word 9, Excel 9 или тот же Power Point 9. В состав этой библиотеки входит корневой объект Application ( Word9.Application, Excel9.Application и т.д.). Этот корневой объект и определяет основную структуру документа. Но помимо этой библиотеки в каркас всегда входят и другие библиотеки. Взгляните на каркас по умолчанию документа Word:

    (рис 1.2) Каркас по умолчанию документа Word

    Как можно видеть, в каркас входят кроме библиотеки Word еще три библиотеки и два проекта:

  • Word - библиотека, задающая основу документов Word. Здесь хранится корневой объект Application и все классы объектов, вложенных в корневой объект.
  • Office - библиотека объектов, общих для всех приложений Office 2000. Здесь находятся классы, задающие Помощника (объект Assistant и все классы, связанные с ним). Здесь же находятся классы, определяющие инструментальные панели - CommandBar и классы других общих объектов. В частности, появился новый объект, которого не было в предыдущей версии - Мастер Ответов (Answer Wizard) и его файлы.
  • Stdole - библиотека классов, позволяющая работать с OLE - объектами и реализовать Автоматизацию.
  • VBA - библиотека классов, связанных с языком VBA. Здесь хранятся все стандартные функции, встроенные в язык, и многое другое.
  • Project - проект по умолчанию, связанный с документом. Классы, которые могут программистом создаваться в этом проекте, методы, свойства, - все это доступно для просмотра, так же, как и объекты классов, встроенных в стандартные библиотеки.
  • Normal - проект, доступный для всех документов Word. Здесь могут храниться функции и классы, используемые всеми документами.
  • Состав каркаса для документов, открываемых в Excel или Power Point, почти такой же. Естественно, библиотека Word заменяется библиотекой соответствующего приложения. Кроме того, отсутствует проект Normal, характерный только для документов Word.

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

    А теперь о том, как это делается. Прежде всего, заметим, что расширение каркаса делается руками, а не программно. Для того чтобы добавить в документ новые возможности, необходимо вначале войти в режим редактора программного проекта, для чего достаточно из меню Tools | Macro выбрать пункт Visual Basic Editor или нажать комбинацию клавиш Alt + F11. Затем уже в Редакторе из меню Tools следует выбрать пункт References и в появившемся списке всех возможных библиотек, включить те, которые отвечают Вашим потребностям. На рис. 1.3 показан процесс подключения к документу Word новых библиотек.

    (рис 1.3) Расширение возможностей каркаса документа

    В частности, мы подключили библиотеки объектов трех приложений - Outlook, Access и Excel, библиотеку с WEB - компонентами, Мастер этих компонент и элемент управления для работы в Internet. В результате каркас документа существенно обновился, и наш документ теперь обладает потенциально большими возможностями, чем документ, создаваемый по умолчанию. В этом документе можно организовать совместную работу четырех приложений Office 2000, работать с WEB - компонентами и использовать возможности встроенного элемента управления при работе над документом в Internet. Конечно, каркас обеспечивает только потенциальную возможность, чтобы все заработало, нужно многое сделать, наполняя каркас плотью. Например, необходимо описать и создать соответствующие объекты Application для каждого из совместно работающих приложений, прежде чем начать с ними работать.

    На рис. 1.3 можно увидеть лишь небольшую часть всей совокупности библиотек (их несколько десятков), доступных в Office 2000. Профессионалу знать их, конечно, совершенно необходимо. Но знакомство с ними, хотя бы шапочное, выходит за пределы этой книги, посвященной VBA . О них и об объектах, в них хранящихся, пойдет разговор в других книгах, связанных общей темой офисного программирования в среде Office 2000.

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

    (рис 1.4) Окно просмотра объектов каркаса документа

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

    Библиотека объектов Office 2000 и Object Browser

    Мы уже говорили, что Office 2000, так же как и Office 97, задается совокупностью библиотек классов. Каждому приложению соответствует своя библиотека классов объектов. Кроме того, есть библиотеки с общими для всех приложений классами объектов. Библиотеки классов, задающих приложения, устроены одинаково. Есть корневой класс (корневой объект) Application (Excel, Word и т.д.). Это "толстый объект", как матрешка. В него вложено большое число объектов, эти объекты задают свойства корневого объекта и являются так называемыми свойствами - участниками. Помимо этого корневой объект имеет терминальные свойства, методы и события. Каждый вложенный объект устроен аналогично - он тоже "толстый", может быть более толстый, чем корневой.

    Сложность самой системы и большое количество составляющих ее объектов не позволяют описать все эти объекты в книгах наподобие этой. Необходимо также обращаться за справками к электронной документации. Справочная система по объектам в Office 97 была сделана, на наш взгляд, совсем неплохо, в Office 2000 она только улучшена. У Редактора VBE (Visual Basic Editor) есть инструментальное средство Object Browser (Окно просмотра объектов или, как теперь принято говорить, браузер объектов). Он позволяет просмотреть объекты, которые могут быть использованы в документе, увидеть их структуру - свойства, методы, события, получить справку и (или) пример использования.

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

    В браузере можно выбрать одну из библиотек каркаса документа, просмотреть ее структуру, для каждого класса объектов просмотреть его свойства, методы и события и тут же получить справку по каждому элементу. Вызывается Object Browser из редактора VBE выбором из меню пунктов View | Object Browser. А можно и быстрее: напомним, редактор вызывается нажатием клавиш Alt +F11, а Object Browser - F2.

    Взгляните еще раз на рис. 1.2 и рис. 1.4 , где показан Object Browser. В левом верхнем углу окна просмотра объектов расположен раскрывающийся комбинированный список Project/Library, содержащий имена доступных проектов и библиотек. В окне Classes отображается структура выбранного из списка класса или проекта - совокупность встроенных объектов. Выбрав один из объектов, в соседнем окне Members Вы увидите элементы этого объекта (свойства, методы, события). Каждый элемент - библиотека, класс, проект, свойство, метод, событие, свойство типа перечисление - сопровождается соответствующим значком. Щелкнув кнопку "справка" (со значком "?"), Вы получите быструю справку по выбранному элементу.

    Крайне полезное нововведение, сделанное в Office 2000, состоит в том, что в открывшемся окне справки можно щелкнуть кнопочку печати, позволяющее тут же напечатать справку. Более важно, что по другой кнопочке можно перейти в окно поиска информации по индексу, по оглавлению и в диалоге с Мастером Ответов (Answer Wizard). Единственный недостаток, справка и книги документации не согласованы, как это сделано в среде Visual C++, так что, найдя справку, вы не можете перейти в книгу документации, из которой эта справка взята, и просмотреть связный контекст. Так что есть еще место для совершенства справочной системы.

    Следует заметить, что в Office 2000 справку выдает Мастер ответов, обладающий новыми возможностями. Его можно настроить так, что он будет выдавать справки и по объектам, спроектированным программистом.

    Просматривать все объекты в поисках нужного - занятие довольно утомительное, поэтому в Object Browser имеются инструменты поиска. Ниже окна Project/Library расположен еще один комбинированный список, где нужно задать имя элемента поиска, а затем щелкнуть рядом расположенную кнопку поиска. При необходимости поиск можно осуществлять в одной из библиотек или во всех библиотеках (All libraries). Результаты поиска отображаются в специальном окне Search Results. На рис. 1.5 показаны результаты поиска слова Data в одной из библиотек.

    (рис 1.5) Окно с результатами поиска

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

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

    Объекты Application

    Всех объектов в Office 2000 не перечесть, но знать главные - обязательно. Давайте начнем знакомство с корней - объектов Application. Заодно посмотрим, что нового появилось в структуре этих объектов в сравнении с предыдущей версией. Чтобы облегчить и систематизировать нашу работу, мы по отдельности рассмотрим свойства - участники, терминальные свойства, методы и события этих объектов.

    Свойства-участники

    Свойства, представляющие вложенные объекты, называют свойствами-участниками. Если X является свойством - участником объекта Application, то обращение к свойству X возвращает ссылку на объект X. Обращение Application.X.Y.Z, где X, Y и Z - свойства-участники, позволяет добраться до объекта Z, находящегося на третьем уровне вложенности. Обычно цепочка именования начинается спецификатором (объектом) Application, но иногда его можно опустить. Некоторые свойства и методы объекта Application относятся к глобальным. Для них спецификатор Application разрешается опускать, непосредственно именуя глобальный элемент. Вот пример нескольких обращений к элементам объекта Application:

    Application.ActiveDocument ' Можно короче: ActiveDocument
    Application.ActiveWorkbook.ActiveSheet.Range("A1") = "Hi"' Можно так:
    ActiveSheet.Range ("A2") = "By-By"	' Можно и так:
    Range("A3") = "I'm glad to see you"  'Можно даже так!
    Application.Quit 'Только так! Quit не является глобальным методом.

    Познакомимся на верхнем уровне со структурой приложений и посмотрим, как она изменилась при переходе от Office 97 к Office 2000. На рис. 1.6 , рис. 1.7 , рис. 1.8 и рис. 1.9 показано, как выглядели объекты Application четырех основных приложений в Office 97. Что можно отметить, анализируя эту структуру:

  • Среди объектов, вложенных в Application, есть основные, задающие специфику приложения, - это документы Word (коллекция объектов Document ), рабочие книги Excel (коллекция объектов WorkBook ), презентации PowerPoint (коллекция объектов Presentation ), отчеты Access (коллекция объектов Report ). Позже мы познакомимся с ними подробнее, сейчас же отметим только, что каждый из них организован не менее сложно, чем их родитель - объект Application. Кроме основных объектов есть и вспомогательные объекты, специфичные для данного приложения. Например, у приложения Word это коллекции CustomDictionaries, Languages - коллекции пользовательских словарей и языков, используемых в документах Word.
  • Есть объекты, общие для всех приложений. К ним относятся коллекции, CommandBars, Dialogs, Windows объекты Assistant, FileSearch, VBE. Эти объекты хранятся в библиотеке Office, присоединяемой к каркасу каждого документа. Они определяют такие общие для всех документов свойства, как возможность работы с инструментальными панелями, содержащих меню, элементы управления и кнопки; использование стандартных диалогов в документах и другие свойства, задающие, в целом, единый интерфейс документов в среде Office 2000.
  • На общем фоне в Office 97 выделяется объект Access.Application. Структура его бедна. У него нет общих объектов, весьма ограничено число вспомогательных объектов, определяющих специфику данного приложения.
  • (рис 1.7) (рис 1.6) (рис 1.9) (рис 1.8)

    Что же нового появилось в Office 2000? Прежде всего, следует отметить, что все свойства, которыми объекты обладали, у них остались. Но, конечно, появились и новые свойства. Ниже в таблице показаны основные, новые свойства, встроенные в объекты Application в Office 2000.

    Новые свойства объектов Application в Office 2000
    Свойства Word Excel Power Point Access
    AnswerWizard + + + +
    COMAddIns + + + +
    LanguageSettings + + + +
    EmailOptions + - - -
    DefaultWebOptions - + + -
    MsoDebugOptions - - + -

    Появилась возможность подключения COM - объектов, расширяющих функциональные возможности документов; коллекция COMAddIns стала частью библиотеки общих объектов Office 2000. Напомним, что ранее каждое из приложений имело свою специфическую для данного приложения коллекцию AddIns. Каждый из элементов AddIn дополнял приложение новыми функциями, но мог работать только в рамках одного приложения. Этим коллекциям и компонентному программированию будет посвящена отдельная лекция этой книги.

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

    Особо следует отметить и другую линию существенных изменений, направленных на унификацию средств, используемых в разных приложениях. Так объект Access.Application приблизился к своим "братьям" и по структуре свойств в меньшей степени выбивается из общего ряда. Объекты из библиотеки Office, задающие общие для приложений Office 2000 свойства, теперь доступны и в Access Заметим, правда, что сама библиотека Office все еще не подключается по умолчанию при создании каркаса документа Access. Однако, теперь, как и в общем случае, можно щелчком Alt+F11 вызвать Редактор VBE и в меню References подключить эту и другие библиотеки.

    Важно и то, что у объекта Access.Application, как и положено, помимо главных свойств ( Forms, Reports, Modules ) появились на верхнем уровне и дополнительные свойства - участники. Отметим некоторые из них:

  • CodeData. Этот объект позволяет получить доступ к разнообразным коллекциям данных - AllQueries, AllTables, AllViews, AllDataBaseDiagrams, AllStoredProcedures - запросам, таблицам, диаграммам, хранимым процедурам.
  • CodeProject. Этот объект позволяет получать доступ к коллекциям основных объектов приложения - AllForms, AllMacros, AllModules, AllReports, AllDataAccessPages. У объекта есть и методы, позволяющие, например, устанавливать связь с базой данных - OpenConnection, CloseConnection.
  • CurrentData. Представляет косвенную ссылку на текущий объект данных и обладает всеми свойствами объекта CodeData.
  • CurrentProject. Представляет косвенную ссылку на текущий проект и обладает всеми свойствами объекта CodeProject.
  • DBEngine. Объект, представляющий машину вывода со всеми обычными для этого объекта свойствами и методами, как, например, - BeginTrans, CreateDataBase, CreateWorkSpace, OpenConnection - начать транзакцию, создать базу данных, рабочее пространство, открыть связь.
  • DataAccessPages. Эта коллекция объектов, задающих страницы доступа к данным. Каждый из этих объектов содержит такие свойства, как WebOptions, ConnectionString и другие.
  • Вторая группа терминальных свойств

    Объекты Application помимо свойств, заданных вложенными объектами, обладают "терминальными" свойствами. Их задают переменные языка программирования, типы которых непосредственно встроены в язык, - string, integer и т.д. Терминальные свойства также могут быть как специфическими, так и общими для всех приложений, определяя, например, свойства окна, в котором работает приложение. Терминальные свойства просты для понимания, мы не будем на них подробно останавливаться, ограничимся одним примером использования общих свойств. Приведем два макроса, один из которых изменяет размеры окна, предварительно запомнив текущие размеры и состояние окна. Второй из макросов восстанавливает прежние размеры.

    'Объявление переменных на уровне модуля
    Dim LeftW As Long, TopW As Long, HeightW As Long, WidthW As Long
    Dim StateW As WdWindowState
    
    Sub ChangeSizeWindow()
        With Application
    'Запоминаем характеристики окна
            StateW = .WindowState
            LeftW = .Left
            TopW = .Top
            HeightW = .Height
            WidthW = .Width
    ' Изменяем характеристики окна
            .WindowState = wdWindowStateNormal
            .Left = 100
            .Top = 100
            .Height = 400
            .Width = 400
        End With
    End Sub
    
    
    
    Public Sub ResetSizeWindow()
    With Application
    ' Восстанавливаем характеристики окна
            .Left = LeftW
            .Top = TopW
            .Height = HeightW
            .Width = WidthW
            .WindowState = StateW
    End With
    End Sub

    Эту пару макросов можно применять к трем приложениям Office 2000, поскольку в каждом из них объект Application обладает терминальными свойствами Left, Top, Height, Width, WindowState. Единственное, что придется поменять, - тип переменной StateW и задающую статус окна константу wdWindowStateNormal, так как у каждого из приложений свои имена констант и свои типы для них, хотя они и задают одинаковые значения. Заметьте: по имени константы можно определить ее тип и назначение. Так, константы Word начинаются префиксом " wd ", а константы Excel - " xl ".

    Следует отметить, что, Access продолжая выделяться, этих терминальных свойств еще не приобрел.

    Замечание.

    Все примеры этой книги мы старались проверить непосредственно на машине. С этой целью, как правило, для проверки соответствующего примера в тестовом документе создавалась командная кнопка, в ответ на щелчок которой вызывался соответствующий макрос, текст которого и приводится в книге. На рис. 1.10 показан такой тестовой документ, для проверки примеров этой лекции.

    (рис 1.10) Тестовый документ с командными кнопками

    Методы объектов Application

    Казалось бы, объекты Application не должны иметь много методов, а среди имеющихся методов большая часть должна быть общей для приложений разных типов. Ведь специфика приложения должна проявляться на более низком уровне иерархии, когда начинается работа, например, с документами Word или рабочими книгами Excel. Но это не так, - реально методов много, а общих методов мало. Более того, даже методы Activate, Run, Quit, имеющиеся у всех приложений, совпадающие по именам и предназначенные для решения стандартных задач (активизация приложения, запуск макроса, выход из приложения) организованы по-разному. Так, метод Quit() в Excel не имеет параметров - он, естественно, завершает приложение. А вот в приложении Word у этого метода 3 параметра: Quit([SaveChanges], [OriginalFormat], [RouteDocument]), - позволяющие в момент выхода указать, сохранять ли сделанные изменения и их формат, пересылать ли документ всем, кто работает с ним.

    Лишь приложение Power Point "правильно" устроено с нашей точки зрения, - его объект Application имеет всего четыре метода; помимо трех методов, только что перечисленных, у него еще есть метод Help. Это тоже один из общих методов, которого нет только у приложения Access.

    Из общих в Office 2000 методов для Word, Access и Excel отметим группу DDE-методов, обеспечивающих динамический обмен данных. Word и Excel имеют общий метод OnTime, о котором стоит рассказать подробно. Он позволяет запустить некоторый макрос в заданное время. Каждое утро, например, можно запускать макрос, позволяющий провести антивирусную профилактику, сохранить резервные копии и т. п. Синтаксис метода в приложении Word таков:

    OnTime (When, Name, Tolerance)

    Первый обязательный параметр When задает время запуска - некоторое выражение, значением которого является строка, задающая время. При задании этого параметра часто используются функция Now, которая возвращает текущее время, и функции TimeValue и TimeSerial, преобразующие время, заданное в относительно произвольной форме к фиксированному стандарту.

    Параметр Name - также обязательный - задает имя запускаемого макроса. Макрос должен быть доступен как в момент выполнения процедуры OnTime, так и когда наступает время его выполнения, указанное в параметре When. Поэтому разумно такие макросы помещать, например, в проект Normal, доступный для всех приложений Word.

    Параметр Tolerance задает диапазон времени, в течение которого есть смысл запустить макрос, если он не смог быть запущен в указанный параметром When момент. Причин, по которым макрос нельзя запустить в точно указанный срок, может быть много, - например, идет модальный диалог, который нельзя прервать до его завершения.

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

    Sub InTime()
    	'Запуск одного из двух макросов "Приветствие"
    	'Один запускается по утрам в 10.00, другой - через 1 минуту,
    	'начиная отсчет от момента выполнения метода OnTime
    	If Now < "10:00:00" Then
    			Application.OnTime TimeValue("10:00 am"), "Morning"
    	Else
    			Application.OnTime Now + TimeValue("00:01:00"), "Hello"
    	End If
    End Sub

    Заметьте: запускается только один из макросов. "Завести два будильника", дважды вызвав метод OnTime, нельзя - ведь только один таймер следит за запуском макроса. Пока "заведенный" макрос не будет исполнен, любая попытка установить время для запуска следующего макроса приведет к отмене предыдущего указания.

    Для полноты картины приведем тексты макросов-приветствий:

    Sub Morning()
    	' Утреннее приветствие
    	MsgBox Prompt:="Привет! Я рад, работать с Вами!", Buttons:=vbOKOnly
    End Sub
    
    Sub Hello()
    	'Приветствие
    	MsgBox Prompt:="Привет! Будем работать!", Buttons:=vbOKOnly
    End Sub

    Итак, подводя итоги, отметим, что только объект Power Point.Application имеет всего четыре метода. Остальные объекты Application имеют десятки методов, большей частью отражающих специфику приложения. Например, в Office 2000 объект Access.Application имеет:

  • Группу из 9 методов Create, позволяющих программно создать проект, элемент управления, форму, отчет и другие элементы приложения.
  • Группу D - функций, общих с Excel, позволяющих работать с запросами над списками Excel.
  • Группу Get и Set - методов, позволяющих, например, получить или установить те или иные опции.
  • Методы Open, Close, New, позволяющие открывать, закрывать или делать текущей новую базу данных.
  • Другие методы.
  • Следует понимать причину "изобилия" методов у объектов Application. Дело в том, что большинство методов, это, фактически, методы объектов нижних уровней, вынесенные на верхний уровень иерархии.

    Один и тот же метод X может быть определен как для объекта Application, так и для объектов разных классов, вложенных на разных уровнях иерархии. Иногда это позволяет выполнять массовые операции над всеми объектами, входящими в иерархию. Так, метод Calculate в Excel применим к объектам Application, WorkBook и Worksheet. Вызов Application.Calculate приведет к запуску вычисления формул всех рабочих листов всех рабочих книг.

    Но будьте осторожны: методы - "тезки" могут отличаться параметрами и реализацией. Например, методы проверки правописания и грамматики CheckSpelling и CheckGrammar определены для трех объектов Word: Application, Document и Range. Вызванные объектами Document и Range, они проверяют текст в диапазоне, связанном с объектом, вызвавшим метод. А у одноименных методов объекта Application появляется дополнительный параметр, задающий проверяемую строку.

    Еще один пример - метод Move, которым обладают объекты:

  • Application, Task, Range, Selection - в приложении Word;
  • Chart, Charts, Worksheet, Worksheets, Sheets в приложении Excel;
  • общие объекты Assistant, CommandBarControl из библиотеки объектов Office;
  • Control, Controls из библиотеки объектов MSForms.
  • За общим именем скрываются похожие, но разные по количеству параметров и по действию методы. В ООП одноименные методы одного или разных классов, различные по количеству и типам параметров и (или) реализации, называются перегруженными. В Office 2000 широко применяется перегрузка методов. С этим часто приходится сталкиваться при получении справок в электронной документации, например, по уже упомянутому методу Move, когда приводятся несколько его перегруженных вариантов. В этом случае дается список классов, обладающих данным методом. Выбрав класс, можно получить справку по конкретной реализации метода в данном классе.

    Осталось еще рассказать, какие новые методы появились у Application -объектов приложений Word, Access и Excel в Office 2000 в сравнении с предыдущей версией Office 97. Общих новых методов нет.

    В приложении Word у объекта Application появилось 8 новых методов. Два из них расширяют набор метрических преобразований, четыре определены над клавиатурой и связаны с расширенной поддержкой национальных языков в Office 2000. Еще один метод следует упомянуть подробнее, - речь идет о функции DefaultWebOptions, возвращающей объект подобного класса. Если взглянуть на ранее приведенную таблицу новых свойств, то можно заметить, что приложения Power Point и Excel имеют новое свойство, возвращающее объект этого класса. Приложение Word вместо этого имеет метод, возвращающий тот же объект. Один Access пока что не имеет ни подобного свойства, ни метода.

    В приложении Excel, как ни странно, нет новых методов, Более того, исчезли два старых метода: CentimetersToPoints, InchesToPoints, занимающихся метрическими преобразованиями. Вместо того, чтобы добавлять новые методы этой группы, как это сделано в Word, решили убрать эту группу методов из ведения объекта Application.

    Больше всего новых методов появилось у объекта Access.Application, - их 18. Прежде всего, пополнилась группа Create - методов. Теперь можно создавать не только формы и отчеты, но и проекты ( CreateAccessProject ), страницы доступа ( CreateDataAccessPage ), элементы управления с расширенным набором свойств, размещаемые, возможно, в отчете( CreateControlEx, CreateReportControlEx ). С проектами работают еще два метода, - OpenAccessProject, NewAccessProject. Несколько методов добавлено для работы с текстами. Детали оставим на будущее.

    События объектов Application

    У объекта Access.Application событий нет. Все события вынесены на более низкий уровень иерархии и возникают при работе с документами Access - отчетами, формами и т.д.

    Объекты Application приложений Word, Excel и Power Point имеют примерно одинаковый набор событий. Фактически эти события возникают при работе с объектами нижних уровней иерархии - окнами, документами Word, рабочими книгами и страницами ( Sheets ) Excel, презентациями и слайдами Power Point. Всякий раз, когда окно или тот или иной документ создается, открывается, изменяется, закрывается, - возникает соответствующее событие, которое можно обработать. Обработчик события можно связывать непосредственно с самим объектом, при работе с которым событие возникло. Но иногда удобнее вынести обработчик на верхний уровень приложения и связать его с объектом Application. Это особенно полезно, если один и тот же обработчик применяется ко всем документам приложения.

    Совместная работа приложений. Создание объектов Application. Раннее и позднее связывание

    Мы уже не раз говорили, что эффективность работы в среде Office 2000 во многом определяется возможностью совместной работы его приложений. С программистской точки зрения это означает, что в документе одновременно определены несколько объектов Application, задающих совместно работающие приложения. Давайте рассмотрим, как обеспечивается такая возможность. При открытии какого - либо из приложений, например, документа Word по умолчанию считается определенным соответствующий объект Application, а следовательно и все объекты, в него вложенные. Более того, определены и все объекты, входящие в каркас документа, построенный по умолчанию.

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

  • Расширить каркас документа Word, установив ссылки на библиотеки, содержащие приложения Excel и Access . Напомним, что это делается в редакторе VBE в окне References меню Tools.
  • Объявить объекты (указатели на объекты) соответствующего класса.
  • Создать объекты и связать указатели с вновь созданными объектами.
  • Когда корневой объект Application создан и доступен, то автоматически становятся доступными все вложенные в него объекты, так что теперь с приложением можно работать в обычном режиме, вызывая свойства и методы его объектов. При объявлении объектов возможны варианты. При этом следует помнить, что объекты в VBA задаются с помощью указателей. Рассмотрим три возможных варианта объявления:

  • Dim MyXlApp As Object, MyAcApp As Object Этот вариант задает так называемое позднее связывание. На этапе объявления известно, что MyApp переменные являются объектами, а точнее, указателями на объекты, но еще не известно с объектами какого класса они будут связаны. Это станет известно динамически, в ходе выполнения программы, когда реально будет создан объект - экземпляр соответствующего класса и наш указатель получит на него ссылку. Для программиста эти переменные являются нетипизированными указателями.
  • Dim MyXlApp As Excel.Application, MyAcApp As Access.Application Это объявление задает раннее связывание. Наши переменные теперь представляют собой типизированные указатели. И уже на этапе объявления известно, что в дальнейшем они будут связаны с объектами соответствующего класса. Чтобы при этом объявлении не возникло конфликтов, конечно же, необходимо предварительно подключить соответствующую библиотеку. Важно также понимать, что на этапе объявления память выделена только указателям. Сами объекты еще не созданы, и потому значения указателей не определены. Объекты еще предстоит создать по ходу выполнения программы и указатели должны быть связаны с ними.
  • Dim MyXlApp As New Excel.Application, MyAcApp As New Access.Application В этом случае раннее связывание реализуется в полном объеме. Создается указатель, благодаря спецификатору New создается сам объект, и указатель получает ссылку на вновь созданный объект.
  • Эти три варианта характерны не только при работе с объектами Application, а во всех случаях работы с объектами. Конечно же, в большинстве случаев предпочтительнее третья конструкция, когда создание объекта и указателя совмещаются в одном операторе. В Office 2000 такая конструкция является допустимой для объектов Application и ее разумно использовать.

    Заметьте, что не все приложения допускают конструкцию New для создания Active X объектов, каковыми являются объекты Application. В ряде случаев для создания Active X объектов, хранящихся в отдельных файлах, следует использовать метод CreateObject, первый параметр которого задает имя класса объекта. Этот метод следует выполнить в нужный момент, связав заодно указатель с вновь созданным объектом. Конечно, и в Office 2000 допустимо создать объекты Application следующим образом:

    Set MyXlApp = CreateObject("Excel.Application ")
    Set MyAcApp = CreateObject("Access.Application ")

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

    В заключение рассмотрим пример, иллюстрирующий работу трех приложений: Word, Excel и Access:

    Public Sub WorkWithExcel()
    'НЕ забудьте включить ссылку на Excel в меню References
     'Объявление и создание объектов Excel.Application
            Dim MyXlApp As New Excel.Application
        'Работа с приложением Excel
        With MyXlApp
                .Visible = True
            'Excel появился на линейке и его можно раскрыть
             'Добавить новую книгу
           .Workbooks.Add
                'Теперь можно работать и с ячейками данной книги
                .Range("A1") = "Hello!"
                'Идет работа с книгой
                .Range("B1") = "By-By"
            .Workbooks(1).Activate
             'Закрываем открытую книгу
             MsgBox ("Закрываем рабочую книгу Excel?")
            .Workbooks(1).Close
            'Будет задан вопрос о необходимости сохранения книги
             'Закрываем приложение
         .Quit
        End With
    End Sub
    
    Public Sub WorkWithAccess()
    'НЕ забудьте включить ссылку на Access и Dao 3.6 в меню References
    'Приложение Access и его компоненты:
    'База данных, форма и путь к базе
    Dim MyAc As New Access.Application
    Dim MFDb As Database
    Dim FormPoetAges As Form
    Dim PathDb As String
    'Открываем базу данных Access
        PathDb = "E:\O2000\CD2000\Ch1\AgeOfPoet.mdb"
        MyAc.OpenCurrentDatabase (PathDb)
        Set MFDb = MyAc.CurrentDb
    'Открываем форму
    	MyAc.DoCmd.OpenForm ("AgeOfPoets")
    	Set FormPoetAges = MyAc.Forms("AgeOfPoets")
    	MyAc.Visible = True
    	FormPoetAges.SetFocus
    
    'Закрываем базу данных
    	MsgBox ("Закрываем базу данных Access?")
    	MyAc.Quit
    End Sub

    Макросы WorkWithExcel и WorkWithAccess могут быть вызваны из приложения Word. В наших тестовых примерах мы вызывали их в ответ на щелчок соответствующих командных кнопок. Заметьте, второй пример довольно содержателен. Здесь показано, как, не выходя из документа Word, просматривать и редактировать данные формы, созданной в приложении Access для работы с базой данных.

    На этом мы прервем знакомство с корневыми объектами Application. Помните, явно или неявно они всегда будут присутствовать в наших примерах.

    Коллекции в Office 2000

    Почти половина классов объектов в Office 2000 являются коллекциями. Это объясняется тем, что элементы большинства классов можно объединить в упорядоченную совокупность, получив тем самым новый класс - коллекцию элементов. Коллекция это способ организации динамической структуры данных, и потому методы коллекций во многом схожи между собой. Но поскольку специфика элементов различна, то, как следствие, коллекции имеют и специальные свойства и методы. В современных языках программирования коллекции становятся столь же употребительной частью языка, как массивы. Рассмотрим некоторые коллекции объектов Office 2000 и те вариации, которыми они отличаются друг от друга.

    Коллекции объектов Office 2000

    Мы уже говорили, что коллекцию можно рассматривать, как структуру данных, способ их организации. При таком подходе свойства и методы коллекции определяют эту структуру и не учитывают специфику объектов, составляющих коллекцию. Этот подход характерен для класса Collection языка VBA. В других приложениях Office 2000 преобладает несколько иная точка зрения: здесь для большинства коллекций учитываются особенности их объектов, что находит отражение в появлении специфических свойств и методов у различных коллекций. Сейчас мы подробно рассмотрим некоторые коллекции объектов Office 2000. Выбранные для ознакомления коллекции интересны сами по себе, ввиду их широкого использования. С другой стороны, нам важно дать общее представление о возможных вариациях при организации специальных коллекций. Надеемся, приведенных примеров будет достаточно для ориентации во всех имеющихся классах коллекций.

    Коллекции Excel: Workbooks, Sheets

    "Excel позволяет одновременно работать с одной или несколькими рабочими книгами. Каждая книга состоит из одного или более листов. Листы бывают разных типов: рабочие листы, диаграммы, модули, листы макросов. Один из наиболее употребительных - рабочий лист - состоит из совокупности ячеек. Мощь Excel во многом определяется операциями, которые можно выполнить над ячейками рабочего листа…"

    Примерно так можно было бы начать описание Excel. Мы начали его с введения основных понятий. При объектном подходе каждому понятию ставится в соответствие класс объектов. В терминах классов и объектов это же описание Excel может выглядеть так:

    "Объект Application. Excel, представляющий приложение Excel, имеет свойство-участник (встроенный объект) WorkBooks, возвращающее объект WorkBooks - коллекцию всех открытых рабочих книг. Каждый элемент коллекции - рабочая книга - является объектом класса WorkBook.

    Объект WorkBook, представляющий одну рабочую книгу, имеет свойство Sheets. При обращении к этому свойству возвращается объект Sheets - коллекция листов данной книги. Каждый элемент коллекции - лист - имеет свой тип и потому является объектом, например, класса Worksheet (рабочий лист) или Chart (диаграмма).

    Объект Worksheet, представляющий один рабочий лист, имеет свойство Cells, возвращающее объект Range. Используя этот объект, можно задавать как все ячейки рабочего листа - всю таблицу, так и любую ее часть…"

    Как видите, при объектном подходе к изучению Excel мы начинаем с введения классов объектов и заметьте, коллекции появляются уже на первых шагах. Коллекции WorkBooks, Worksheets представляют центральные понятия Excel. С них мы и начнем подробное рассмотрение коллекций объектов Office 2000.

    Коллекция Workbooks

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

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

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

    Add(Template)

    Необязательный параметр Template задает шаблон создания книги. Этот параметр может быть строкой, задающей имя файла, который хранит некую рабочую книгу. В этом случае книга играет роль шаблона для создания новой книги. Параметр Template может также принимать значение одной из предопределенных констант: xlWBATChart, xlWBATWorksheet, xlWBATExcel4IntlMacroSheet, xlWBATExcel4MacroSheet. В этом случае создается рабочая книга с одним листом, тип которого и задает константа. Если же параметр Template опущен, то создается книга с несколькими пустыми листами, число которых устанавливает свойство SheetsInNewWorkbook.

    У метода Open более десяти параметров. Обязательным является только первый - FileName. Он должен быть строкой, которая задает имя файла, хранящего книгу.

    Чтобы удалить рабочую книгу из коллекции, нужно закрыть соответствующий файл (в коллекцию входят лишь открытые рабочие книги). Закрытие книги и, следовательно, ее удаление выполняет метод Close. Он определен как для коллекции, так и для рабочей книги - объекта класса WorkBook. В первом случае метод Close не имеет параметров и закрывает всю коллекцию - все рабочие книги. Чаще всего этот метод вызывается объектом - рабочей книгой для своего закрытия. В этом случае его синтаксис:

    Close(SaveChanges, FileName, RouteWorkbook)

    Все параметры являются необязательными. Первый - булевого типа: если его значение True, сделанные изменения будут сохранены, в противном случае они не сохраняются. Когда же этот параметр опускается, то при выполнении появляется соответствующее диалоговое окно, в котором свой выбор может сделать пользователь. Второй параметр - FileName - необходим, если речь идет о закрытии новой книги, с которой еще не связано имя файла. Если параметр опущен, а указание имени файла необходимо, то, естественно, появляется диалоговое окно. Третий параметр, как и первый, булевого типа. Он задается, когда рабочая книга может быть направлена нескольким участникам для поочередной работы с ней. Если его значение True, книга направляется следующему по списку ее разработчику.

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

    Item(Index)

    Индекс может указывать порядковый номер книги в коллекции, либо быть именем книги. Заметьте, имя книги это имя файла, в котором она хранится. Когда создается новая пустая книга, то ей по умолчанию система присваивает имя типа " BookN ". При сохранении книги в файле это имя может быть изменено. Метод Item является методом по умолчанию и чаще всего опускается. В этом случае индекс связывается с самим объектом - коллекцией рабочих книг.

    Свойство Count возвращает количество элементов коллекции. Доступно только для чтения, имеет тип возвращаемого значения Long.

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

  • Свойство Application возвращает корневой объект Application.
  • Свойство Creator аналогично свойству Application. Оно возвращает код приложения (32-битное целое), который используется при работе с Macintosh.
  • Свойство Parent возвращает родительский объект (для коллекции WorkBooks это все тот же объект Application ).
  • Метод OpenText является модификацией метода Open. Он создает новую рабочую книгу с одной страницей, используя для ее создания текстовый файл. В процессе открытия происходит анализ и разбор данных, записанных в текстовом файле. Метод имеет 13 параметров, из которых обязателен лишь первый - FileName, задающий имя текстового файла.
  • Приведем теперь пример программы, позволяющий продемонстрировать детали работы с коллекцией WorkBooks. Наша коллекция будет включать как новые, создаваемые в программе, так и ранее существовавшие книги. Книги будут добавляться в коллекцию и удаляться. Отладочная печать позволит проследить за этим процессом.

    Public Sub WorkWithbooks()
    ' Работа с коллекцией книг
    Dim N As Long, i As Byte
    Dim PathDir As String
    PathDir = "e:\O2000\CD2000\Ch1\"
    With Workbooks
        N = .Count
        Debug.Print "Число рабочих книг в коллекции Workbooks "  _
        "при открытии приложения Excel = ", N
        ' Добавление 2-х новых книг
        .Add
        .Add
        'Добавление двух существующих книг
        .Open (PathDir  "BookThree.xls")
        .Open (PathDir  "BookFive.xls")
        N = .Count
        Debug.Print "Число книг после 2-х вызовов методов Add и Open =", N
        Debug.Print "Имена книг в коллекции:"
        For i = 1 To .Count
            Debug.Print .Item(i).Name
        Next
        'Закрытие двух книг и, следовательно, удаление их из коллекции
        .Item(2).Close
        .Item(3).Close
        N = .Count
        Debug.Print "Число книг после двух вызовов метода Close =", N
        Debug.Print "Имена книг, оставшихся в коллекции:"
        For i = 1 To .Count
            Debug.Print .Item(i).Name
        Next
    End With
    
    End Sub

    Вот результаты отладочной печати:

    Число книг в коллекции WorkBooks при открытии приложения Excel =1 
    Число книг после 2-х вызовов методов Add и Open =        5 
    Имена книг в коллекции:
    BookOne.xls
    Book4
    Book5
    BookThree.xls
    BookFive.xls
    Число книг после двух вызовов метода Close =             3 
    Имена книг, оставшихся в коллекции:
    BookOne.xls
    Book5
    BookFive.xls

    Поясним пример. При открытии Excel коллекция WorkBooks состоит из одной открытой книги, в данном случае - книги с именем BookOne. Затем метод Add добавил в коллекцию две новые книги, которые получили имена " Book1 " и " Book2 " соответственно. Еще две книги появляются в коллекции при открытии существующих книг. Затем две книги закрываются, следовательно, удаляются из коллекции. Обратите внимание, удаляются 2-я и 4-я книги коллекции, хотя индексы удаляемых книг имеют значение 2 и 3. Это связано с тем, что после каждого удаления элемента коллекции происходит перенумерация, и книги получают новые индексы.

    Если при работе с элементами коллекции выполняется операция удаления, то работать с индексами элементов крайне опасно, предпочтительнее для задания элементов указывать их имена!

    Коллекция Sheets

    Коллекция Sheets представляет коллекцию листов двух типов: рабочих листов и диаграмм, - так что каждый элемент коллекции может быть объектом одного из двух классов: Worksheet или Chart. Наряду с коллекцией Sheets существуют коллекции Worksheets и Charts. Они представляют коллекции рабочих листов и диаграмм, выделенных из коллекции Sheets. Но объекты, задающие эти коллекции, принадлежат классу Sheets и используют его свойства и методы. К их рассмотрению мы и переходим.

    Когда создается или открывается рабочая книга, она содержит уже некоторое число листов. Так что коллекция Sheets не пуста в момент открытия книги. Для добавления новых листов в книгу используется знакомый нам метод Add:

    Add(Before,After,Count,Type)

    Все параметры являются необязательными. Первые два - Before и After задают позицию вставки листа - индекс листа, перед или после которого вставляется новый лист. Из этих параметров одновременно может быть задан только один. Если оба параметра опущены, вставка производится перед активным листом данной книги. Параметр Count определяет количество вставляемых листов (по умолчанию - 1). Последний параметр определяет тип вставляемых листов, задаваемый соответствующей константой: xlWorksheet, xlChart, xlExcel4MacroSheet, xlExcel4IntlMacroSheet (по умолчанию - xlWorksheet ).

    Замечание:

    Рабочая книга имеет листы четырех типов. Но при вызове свойства Sheets объекта WorkBook возвращается объект класса Sheets с листами только двух типов. Чтобы получить листы других типов, нужно обратиться к другому свойству объекта WorkBook, например Excel4IntlMacroSheet, возвращающему также объект класса Sheets, но содержащий листы с так называемыми международными макросами, созданными под Excel4.

    Следует обратить внимание на то, что:

  • в методе Add класса Sheets нет параметра, задающего ключ элемента. Однако фактически ключ задается. Его роль играет имя листа, заданное в виде свойства Name, имеющееся у листа каждого типа. Имя листа наряду с числовым индексом можно использовать для поиска листа в методе Item.
  • Из коллекции Sheets листы удаляются методом Delete, не имеющим параметров. В такой форме этот метод имеют многие классы объектов, в том числе Sheets, Worksheet и Chart. Если Delete вызывает объект Sheets, удаляется вся коллекция; если же его вызывают объекты Worksheet или Chart, удаляется соответствующий лист.
  • Получить доступ к элементу позволяет метод (свойство) Item:
    Item(Index)
    Параметр Index задает имя или порядковый номер листа. Метод Item является методом по умолчанию и может быть опущен.
  • Напомним, что иногда бывает трудно провести четкую грань, отличающую метод от свойства. Item является классическим примером подобной ситуации и потому в одной части документации он называется методом, а в другой - свойством.

    Класс Sheets имеет уже известные нам свойства: Application, Creator, Parent и Count. Рассмотрим новые возможности, появившиеся у коллекции Sheets:

  • Свойство Visible - имеет значение True, если объект видимый, и False - в противном случае. Для рабочих листов и диаграмм это свойство может быть также задано константой xlVeryHidden (упрятано, да не просто, а очень уж). Если лист имеет это свойство, он становится невидимым и пользователь никак не сумеет его увидеть, пока программно это свойство не будет установлено в True. Тип свойства двоякий: Boolean или Long.
  • Свойства HPageBreak и VPageBreak - возвращают соответственно коллекции горизонтальной и вертикальной разбивки листа на страницы.
  • Метод Copy - позволяет создать новый лист книги, копируя содержимое уже имеющегося листа. Его синтаксис:
    Copy(Before, After)
    Параметры имеют привычный смысл, указывая точку вставки копируемого листа. Только один из них может быть задан при вызове метода. Метод Copy, вызванный без параметров, копирует содержимое объекта в буфер.
  • Метод Move - модификация метода Copy, позволяет передвинуть лист книги в новое положение. Его синтаксис:
    Move(Before,After)
    Параметры имеют тот же смысл, что и в методе Copy.
  • Метод Paste - копирует содержимое буфера. Параметров не имеет.
  • Метод Select - выделяет объект, его вызвавший. Методом Select обладают объекты многих классов. Если его вызывает коллекция Sheets, метод используется без параметров и выделяет все листы коллекции. Если же он вызван отдельным листом, то может иметь параметр:
    Select(Replace)
    Параметр Replace - булевого типа: если он равен True, происходит замена объекта Selection, и выделенным становится лист, вызвавший метод. Если же значение параметра - False, происходит расширение области выделения, так чтобы она включала ранее выделенный объект и новый лист.
  • Методы PrintPreview и PrintOut - позволяют осуществлять просмотр печати и печать объекта, вызвавшего метод. Как и большинство других рассматриваемых методов, они принадлежат многим классам, в том числе классам Sheets, Charts, Chart, Worksheets, Worksheet, WorkBook и др. Его синтаксис:
    PrintOut(From, To, Copies, Preview, ActivePrinter, PrintToFile, Collate)
    Все параметры необязательны. Первые два задают начальную и конечную страницу печати. Если их нет, печать идет с первой по последнюю страницу. Параметр Copies, если указан, задает количество копий при печати. Если значение булевого параметра Preview - True, предварительно происходит просмотр печати, если же параметр опущен или равен False, просмотра перед печатью нет. Параметр ActivePrinter устанавливает имя активного принтера. Значение булевого параметра PrintToFile - True, если предполагается, что результаты печати посылаются не на принтер, а записываются в файл. При этом появляется диалоговое окно, в котором пользователь задает имя файла, хранящего результаты печати. Если значение параметра Collate задано True, будут сличаться результаты копий, выводимых на печать.
  • Метод FillAcrossSheets копирует содержимое области, заданной объектом Range на рабочие листы коллекции. Его синтаксис:
    FillAcrossSheets(Range, Type)
    Параметр Range указывает область копирования. Она должна принадлежать одному из листов коллекции. Этот параметр обязателен. Необязательный параметр - Type - указывает, как происходит копирование. Он может принимать значение, заданное одной из следующих констант: xlFillWithAll, xlFillWithContents или xlFillWithFormulas. Значение по умолчанию - xlFillWithAll.
  • В заключение приведем пример, демонстрирующий большинство методов этой коллекции.

    Public Sub WorkWithSheets()
    'Работа с коллекцией Sheets - листами рабочей книги
    Dim N As Long, i As Byte
    Dim X As Variant
    'Активизация книги Book2
    Workbooks("Book2").Activate
    With ActiveWorkbook.Sheets
        N = .Count
        Debug.Print "Число листов при первоначальном открытии" _
             "книги = ", N
        Debug.Print "Имена листов:"
        For i = 1 To .Count
           Debug.Print .Item(i).Name
        Next
        ' Переименование листов
        .Item(1).Name = "Two"
        .Item(2).Name = "Four"
        .Item(3).Name = "Six"
        'Добавление листов One, Three, Five
        .Add Before:=.Item("Two")
        .Add After:=.Item("Two"), Type:=xlChart
        .Add After:=.Item("Four"), Type:=xlExcel4MacroSheet
        .Item(1).Name = "One"
        .Item(3).Name = "Three"
        .Item(5).Name = "Five"
         N = .Count
         Debug.Print "Число листов книги после вставки" _
                 "3-х листов =", N
         Debug.Print "Имена и типы листов после переименования:"
         For i = 1 To .Count
             Debug.Print .Item(i).Name, .Item(i).Type
         Next
         'Удаление 3-го и 5-го листов
         .Item("Three").Delete
         .Item("Five").Delete
         'Работа с первым листом
         .Item("One").Activate
        'Запуск макроса Fibonachi, заполняющего область листа A1:A20
        'последовательностью чисел Фибоначчи
         Fibonachi
        'Копирование первого листа на вновь создаваемый третий лист
         .Item("One").Copy After:=.Item("Two")
         'Переименование и перемещение листа
         ActiveSheet.Name = "Seven"
         .Item("Seven").Move After:=.Item("Six")
        'Копирование области одного листа на последовательность листов
        X = Array("One", "Four", "Six")
        Sheets(X).FillAcrossSheets Range:=Worksheets("One").Range("A1:A20")
        Debug.Print "Имена,типы листов и содержимое двадцатой ячейки:"
        For i = 1 To .Count
            Debug.Print .Item(i).Name, .Item(i).Type, _
                .Item(i).Range("A20").Value
        Next
    End With
    End Sub

    Работая с тестовым документом - книгой BookOne. Мы последовательно щелкали командные кнопки, запускающие процедуры WorkWithBooks и WorkWithSheets. Вот результаты отладочной печати при работе последней процедуры:

    Число листов при первоначальном открытии книги = 3 
    Имена листов:
    Sheet1
    Sheet2
    Sheet3
    Число листов книги после вставки 3-х листов = 6 
    Имена и типы листов после переименования:
    One           -4167 
    Two           -4167 
    Three          3 
    Four          -4167 
    Five            3 
    Six            -4167 
    Имена, типы листов и содержимое двадцатой ячейки:
    One          -4167          6765 
    Two          -4167         
    Four          -4167          6765 
    Six            -4167          6765 
    Seven       -4167          6765

    Кратко прокомментируем работу программы. Вначале активизируется книга с именем Book2 из коллекции книг, созданных предыдущим макросом. Эта книга содержит три листа со стандартными именами: Sheet1 -Sheet3. Мы добавляем в эту книгу еще три листа разных типов и переименовываем все листы, давая им имена от One до Six. Четыре листа книги являются рабочими листами и имеют тип xlWorksheet (значение константы -4167 ). Третий лист - это лист диаграммы типа xlChart, а пятый является листом макросов и имеет тип xlExcel4MacroSheet.

    Замечание:

    В Office 97 и Бета версии Office 2000 тип листа диаграммы (свойство Type ) устанавливался неверно. Вместо правильного значения, равного -4109, устанавливалось значение 3, что соответствует листу макроса. В процессе тестирования Office 2000 мы сообщили об этой ошибке и надеемся, что в заключительной версии она уже исправлена.

    Затем третий и пятый лист удаляются, и в книге остаются только рабочие листы. Следующие шаги программы демонстрируют работу методов Copy и Move. Вначале активизируется первый лист, вызывается макрос Fibonachi, заполняющий последовательностью чисел Фибоначчи область листа - ячейки A1:A20. Затем создается копия этого листа, и вновь созданный лист - One(2) - помещается после второго листа книги. Он переименовывается, получает имя Seven и перемещается, заняв позицию после листа Six. Метод FillAcrossSheet позволяет скопировать область одного листа в соответствующие области нескольких листов той же книги. Для этого вначале создается массив X с именами листов, в которые будут копироваться данные. Обратите внимание на этот важный, часто используемый метод. Заметьте: в список массива X должен быть включен и лист One, с которого будет производиться копирование.

    Коллекции Word: Documents, Paragraphs и другие

    Word позволяет одновременно работать с одним или несколькими документами. Документы и коллекция документов - это центральные понятия Word. Классы Document и Documents играют для Word ту же роль, что и классы WorkBook и WorkBooks для Excel. Документ Word организован довольно сложно. Текст - основа большинства документов - может быть дополнен рисунками и таблицами, с ним могут быть связаны комментарии и исправления, сноски и колонтитулы и т. д. Но об этом речь впереди, а пока чуть подробнее поговорим о тексте. Конечно, текст можно рассматривать как последовательность символов, его составляющих. Но ведь куда как часто мы оперируем с более крупными единицами! Word использует привычные понятия: символы, слова, предложения, абзацы, разделы.

    Существуют понятия - существуют и классы, соответствующие этим понятиям. Объект Application. Word, представляющий приложение Word, имеет свойство (встроенный объект) Documents. При обращении к свойству возвращается объект класса Documents - коллекция всех открытых документов. Элемент коллекции - документ - это объект класса Document.

    Объект Document, представляющий один документ, имеет свойства:

    Свойство Возвращает
    Characters объект класса Characters, представляющий коллекцию символов текста документа
    Words объект, представляющий коллекцию слов
    Sentences объект, представляющий коллекцию предложений
    Paragraphs объект, представляющий коллекцию абзацев
    Sections объект, представляющий коллекцию разделов или секций документа
    ListParagraphs объект, представляющий коллекцию списков, входящих в текст документа

    Конечно, это лишь часть многочисленных свойств, связанных с текстом документа. Заметьте: данными свойствами обладает не только сам документ. Ими обладают и объекты Selection и Range, представляющие части документа. При этом возвращаемые объекты представляют соответствующие коллекции данной части документа.

    Казалось бы, раз есть коллекции Characters или Words, то должны существовать и классы Character и Word, представляющие отдельный символ или отдельное слово. Но это не так. Элементами коллекций Characters, Sentences и Words являются объекты класса Range. Нет операций, отдельно определенных над символами, словами или предложениями, - они определены над интервалами, последовательностью символов, представляемых объектом Range. Ситуация здесь подобна Excel, где элементами коллекции Cells являются не ячейки, а все тот же объект Range.

    Абзацу и разделу соответствуют свои классы объектов - Paragraph и Section соответственно. Но у нас сейчас разговор пойдет не о классах отдельных объектов, а о коллекциях. Мы начнем с коллекции документов.

    Коллекция Documents

    Коллекция Documents представляет все открытые документы Word. По своим свойствам и поведению она напоминает коллекцию WorkBooks, представляющую все открытые рабочие книги Excel. Поэтому мы будем часто ссылаться на уже описанные свойства и методы коллекции WorkBooks.

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

  • Add - добавляет новые пустые документы;
  • Open - открывает файл, содержащий существующий документ и автоматически добавляет его в коллекцию.
  • Метод Add имеет синтаксис:

    Add(Template,NewTemplate)

    Параметр Template, задающий шаблон открытия документа, является строкой с именем файла, хранящего шаблон. Параметр не является обязательным и, если он опущен, используется стандартный шаблон Normal (файл Normal. dot). Второй параметр (тоже необязательный) - NewTemplate - булевого типа; он равен True, если документ открывается, как шаблон. Так что коллекция Documents содержит не только документы, но и шаблоны.

    У метода Open десять параметров. Обязательным является только первый - FileName ; он задает имя файла, содержащего документ (шаблон). Остальные параметры определяют режимы открытия: пароль, статус файла, преобразование формата при открытии и т. п.

    Документ удаляется из коллекции при его закрытии. Вне коллекции не может существовать открытый документ. Метод Close закрывает документ и одновременно удаляет его из коллекции. Его синтаксис:

    Close(SaveChanges, OriginalFormat, RouteDocument)

    Все параметры являются необязательными. Первый указывает действия, предпринимаемые при закрытии документа, и может быть одной из констант: wdSaveChanges, wdDoNotSaveChanges, wdPromptToSaveChanges. В зависимости от константы сделанные в документе изменения будут сохранены, проигнорированы или решение будет предоставлено пользователю в режиме диалога. По умолчанию изменения сохраняются при закрытии документа. Параметр OriginalFormat указывает формат сохранения документа и может быть одной из констант: wdWordDocument, wdOriginalFormat, wdPromptUser. В первом случае при сохранении используется формат документов Word, во втором - оригинальный формат документа - тот, что он имел при открытии; в последнем случае решение принимает пользователь в режиме диалога. По умолчанию предполагается формат документа Word. Третий параметр - булевого типа - равен True, если документ после закрытия направляется следующему пользователю, который принимает участие в работе над этим документом. Данный параметр имеет смысл лишь при коллективной работе над документом в сети. По умолчанию он равен False.

    Метод Save позволяет сохранять документы (шаблоны) без закрытия и удаления из коллекции. Этот метод имеют как объекты класса Document, так и коллекции - объекты Documents. Если метод Save вызывает коллекция, то сохраняются все документы этой коллекции. При этом его синтаксис:

    Save(NoPrompt, OriginalFormat)

    Оба параметра необязательны. Если значение первого - True, Word автоматически сохраняет все документы, в противном случае возникнет диалог с пользователем о сохранении каждого из документов. Параметр OriginalFormat задает формат сохранения так же, как и в методе Close. У метода Save, используемого для сохранения отдельного документа, параметров нет. Если сохраняется новый документ, с которым еще не связано имя файла, его хранящего, будет вызвано диалоговое окно SaveAs, в котором пользователь задаст это имя и, если надо, путь.

    Для получения доступа к элементу коллекции, как обычно, можно вызвать метод Item. Его единственный параметр Index задает порядковый номер или имя документа в коллекции. Item является методом по умолчанию, так что индекс можно непосредственно указывать у объекта, задающего коллекцию.

    Класс Documents имеет типичные для коллекций свойства:

  • Application ;
  • Count ;
  • Creator ;
  • Parent.
  • Эти свойства мы описали, когда речь шла о коллекции WorkBooks. Закончим рассмотрение этой коллекции примером:

    Public Sub WorkWithDocuments()
    'Работа с коллекцией документов
    Dim N As Long, I As Byte
    Dim PathDir As String
    PathDir = "e:\O2000\CD2000\Ch1\"
    With Documents
        N = .Count
        Debug.Print "Число документов в коллекции Documents "  _
        "при открытии приложения Word = ", N
        ' Добавление 2-х новых документов (второй представляет шаблон)
        .Add
        .Add NewTemplate:=True
        'Добавление двух существующих документов
        .Open (PathDir  "DocThree")
        .Open (PathDir  "DocFive")
        N = .Count
        Debug.Print "Число документов после 4-х вызовов методов " _
             "Add и Open =", N
        Debug.Print "Имена документов в коллекции:"
        For I = 1 To .Count
            Debug.Print .Item(I).Name
        Next
        'Закрытие двух документов и, следовательно, удаление их из коллекции
        .Item(2).Close
        .Item(3).Close
        N = .Count
        Debug.Print "Число документов после двух вызовов " _
             "метода Close =", N
        Debug.Print "Имена документов, оставшихся в коллекции:"
        For I = 1 To .Count
            Debug.Print .Item(I).Name
        Next
    End With
    End Sub

    Приведем результаты отладочной печати (В данном примере испульзуюся документы Dex1, DocFive, DocThree:

    Число документов в коллекции Documents при открытии приложения Word =  1               
    Число документов после 4-х вызовов методов Add и Open =  5 
    Имена документов в коллекции:
    DocFive.doc
    DocThree.doc
    Template2
    Document3
    Dex1.dot
    Число документов после двух вызовов метода Close =   3 
    Имена документов, оставшихся в коллекции:
    DocFive.doc
    Template2
    Dex1.dot

    Обратите внимание на то, что элементы добавляются в начало коллекции, а не в ее конец, как это было при добавлении элементов в коллекцию WorkBooks Excel. При удалении элемента происходит перенумерация индексов, поэтому удаляется второй и четвертый элемент коллекции при последовательном выполнении методов Item(2). Close, Item(3).Close.

    Коллекция Paragraphs

    Свойство Paragraphs, возвращающее коллекцию абзацев, имеют объекты класса Documents, Selection, Range. Абзац - это не только последовательность символов, но и структурно выделенная единица текста, характеризуемая параметрами: отступом или выступом по отношению к границам листа документа, межстрочными интервалами, расположением первой строки, стилем и пр. Конечно, все эти характеристики связаны в первую очередь с самим объектом, точнее с классом Paragraph. Но, как это часто бывает в Office 2000, свойства и методы объекта включаются и в коллекцию, содержащую эти объекты. В какой-то мере происходит наследование снизу вверх.

    У коллекции Paragraphs два метода, типичные для всех коллекций: Item и Add. Первый, как всегда, определяет элемент коллекции, заданный параметром Index. Абзацы не имеют имен, и индекс всегда задает порядковый номер элемента. Нумерация абзацев в коллекции начинается с 1. Метод Add используется для добавления нового пустого абзаца. Его синтаксис:

    Add(Range)

    Необязательный параметр Range указывает точку вставки, - абзац вставляется перед той частью текста, которую задает объект Range. Если параметр опущен, абзац вставляется в конец документа или после объекта Selection и Range, если они вызвали метод Add.

    Для вставки пустого абзаца чаще всего применяются методы объектов Range и Selection: InsertParagraph, InsertParagraphAfter, InsertParagraphBefore. Они не имеют параметров. Новый абзац заменяет текст или вставляется после или перед частью текста, заданного объектом Range или Selection, вызвавшего соответствующий метод.

    Предупреждение:

    Осторожнее с методом InsertParagraph: он заменяет весь имеющийся текст новым, пустым абзацем!

    Для вставки текста в созданный пустой (или непустой) абзац могут быть использованы методы объектов Range и Selection: InsertAfter и InsertBefore. Их единственный параметр - Text - задает текст, добавляемый в начало или в конец части текста, заданной объектами Range и Selection, после чего объекты расширяются, дабы включить добавленный текст. Для удаления абзацев может использоваться метод Delete объектов Range и Selection.

    В коллекции Paragraphs много методов, "наследуемых" у объекта Paragraph. Чаще всего они применяются к отдельному абзацу, но иногда вызываются коллекцией, чтобы применить метод ко всем абзацам коллекции. Вот эти методы:

  • OpenUp, CloseUp, OpenOrCloseUp - вставляют или удаляют фиксированное количество пробелов (12) перед абзацем. OpenOrCloseUp - переключатель: если есть пробелы, он их удаляет, нет - вставляет.
  • Indent и Outdent - увеличивают и уменьшают отступ абзаца (или всех абзацев коллекции) от края листа.
  • OutlineDemote, OutlinePromote и OutlineDemoteToBody - понижают и повышают уровень заголовка в интервале Heading1 : Heading8. При понижении последнего уровня -Heading 8 стиль заголовка меняется на стиль Normal.
  • Reset - удаляет форматирование, сделанное вручную, применяя формат, заданный стилем абзаца.
  • Space1, Space2, Space15 устанавливают в абзаце межстрочный интервал: одинарный, двойной или полуторный.
  • TabHangingIndent(Count) и TabIndent(Count) изменяют выступ или отступ абзаца от края листа на заданное количество позиций, определенное параметром Count. Если значение этого параметра положительно, происходит увеличение, иначе - уменьшение отступа (выступа).
  • Коллекция Paragraphs имеет общие свойства Count, Parents, Creator и Application. Кроме того, есть много свойств и методов, специфических для абзацев. Иногда, одной и той же цели можно добиться, вызывая метод или изменяя свойство. За подробностями отсылаем к документации.

    Коллекция Sections

    Свойство Sections, возвращающее коллекцию разделов, имеют объекты класса Documents, Selection, Range. Разделение документа на разделы позволяет придать документу подходящую структуру. Обычно раздел - довольно крупная единица текста в отличие от абзаца. Например, если документ представляет книгу, то каждый ее параграф или глава может быть выделена в отдельный раздел. При установке разделов вручную из меню Insert выбирается пункт Break, позволяющий закончить предыдущий раздел и начать новый. Раздел кончается специальным символом прерывания определенного типа. В зависимости от типа символа прерывания новый раздел может начинаться:

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

    Вернемся к коллекции Sections. Она имеет свойства, уже известные нам по другим коллекциям. Поэтому мы их только перечислим:

    Application, Count, Creator, Parent, First, Last.

    Новым, ранее не упоминавшимся является свойство PageSetup. При обращении к нему возвращается объект класса PageSetup, свойства и методы которого позволяют установить характеристики страницы одновременно для всех разделов коллекции. Метод Item позволяет получить доступ к элементу коллекции. Метод Add позволяет добавить новый раздел в документ:

    Add(Range, Start)

    Возможный параметр Range указывает объект, перед которым будет вставлен символ прерывания, заканчивающий раздел. После символа прерывания будет начинаться новый раздел объектом Range. Если параметр Range опущен, символ прерывания вставляется в конец документа. Возможный параметр Start определяет тип символа прерывания раздела. Он может быть задан одной из констант:

    wdSectionNewPage, wdSectionContinuous, wdSectionEvenPage, wdSectionOddPage, wdSectionNewColumn

    Смысл, задаваемый этими константами, ранее уже был определен. В зависимости от их значения новый раздел будет начинаться со следующей страницы, на той же странице, на четной и нечетной странице. Последняя константа используется при работе с таблицами, позволяя по-разному форматировать каждый из ее столбцов. Если параметр Start опущен, новый раздел будет начинаться со следующей страницы.

    Для удаления раздела из коллекции может быть использован метод Delete объектов Selection и Range.

    Взгляните на пример работы с текстом документа, в котором создаются новые разделы и добавляются абзацы:

    Public Sub WorkWithSecAndPar()
    'Работа с разделами и абзацами
    'Добавление новой книги
    Documents.Add
    Documents(1).Activate
    With ActiveDocument
        'Вставка двух разделов в документ
        'Раздел начнется с нечетной страницы
        .Sections.Add Start:=wdSectionOddPage
        .Sections.Add
        'Вставка абзаца во второй раздел
        .Sections(2).Range.Paragraphs.Add
        .Sections(2).PageSetup.LeftMargin = 3
        .Sections(2).Range.Style = "Heading 1"
        .Sections(2).Range.Font.Name = "Arial"
        .Sections(2).Range.Paragraphs(1).Range.InsertBefore ("Лекция 1")
        'Вставка нового раздела и абзаца
        .Sections.Add Start:=wdSectionNewPage
        .Sections.Last.Range.Paragraphs.Last.Range.InsertBefore ("Параграф 1")
        .Sections.Last.Range.Paragraphs.Add
        'Вставка нового раздела и абзаца
        .Sections.Add Start:=wdSectionNewPage
        .Sections.Last.Range.Paragraphs.Last.Range.InsertBefore ("Параграф 2")
        .Sections.Last.Range.Paragraphs.Add
        'Вставка нового раздела в конец документа
        'Раздел начнется с нечетной страницы
        .Sections.Add Start:=wdSectionOddPage
        .Sections.Last.PageSetup.LeftMargin = 23
        .Sections.Last.Range.Font.Name = "TimesNewRoman"
        'Вставка абзаца
        .Sections.Last.Range.Paragraphs(1).Range.InsertBefore ("Лекция 2")
        .Sections.Last.Range.Paragraphs.Add
        Debug.Print "Число разделов документа =", .Sections.Count
        Debug.Print "Число абзацев документа =", .Paragraphs.Count
        'Удаление раздела выполняет метод объекта Range
        .Sections(1).Range.Delete
        Debug.Print "Число разделов документа =", .Sections.Count
    End With
    
    End Sub

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

    Sections.Last.Range.Paragraphs(1).Range.InsertBefore ("Лекция 2")
  • Свойство Sections активного документа возвращает объект Sections, задающий коллекцию разделов этого документа.
  • Свойство Last объекта возвращает объект Section, задающий последний раздел в этой коллекции.
  • Свойство Range возвращает объект Range, связанный с данным разделом. Теперь становятся доступны методы и свойства объекта, в частности свойство Paragraphs, которым объект Section не обладает.
  • Вызов Paragraphs(1) возвращает объект класса Paragraph, задающий первый абзац из коллекции абзацев данного раздела. Заметьте: опущен метод по умолчанию Item, так что запись Paragraphs(1) является краткой формой записи Paragraphs. Item (1)
  • И снова мы получаем объект Range, теперь уже связанный с абзацем.
  • На последнем шаге вызывается метод InsertBefore объекта Range, позволяющий добавить в начало абзаца текст, заданный аргументом метода. В нашем случае - лекция 2.
  • Коллекции Characters, Words, Sentences

    Свойства Characters, Words, Sentences возвращающие коллекции символов, слов или предложений, имеют объекты класса Documents, Selection, Range. Все эти коллекции устроены довольно просто. Они имеют известные нам свойства:

    Application, Count, Creator, First, Last, Parent

    и единственный метод Item(Index). Этот метод для всех коллекций возвращает объект Range, позволяющий работать как с единственным символом, так и с совокупностью символов, соответствующей слову или предложению. Добавление в коллекцию и удаление из нее элементов осуществляется методами объекта Range.

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

    Коллекции и конструкция For Each … Next

    При работе с коллекциями довольно часто приходится организовывать цикл по всем элементам коллекции. До сих пор во всех наших примерах мы использовали обычные средства - цикл " For ", где количество шагов цикла определялось свойством Count (его имеет каждая коллекция). Наша конструкция выглядела так:

    With <объект>
    	For i = 1 To .Count
    	.Item(i) 	' Доступ к i-му объекту и работа с ним
    	Next i
    End With

    VBA предлагает специальную конструкцию " For Each " для организации подобных циклов. Синтаксис конструкции таков:

    For Each <Элемент> In <Группа>
    [<Операторы>]
    [Exit For]
    [<Операторы>]
    Next [<Элемент>]

    где:

    <Группа> - имя объекта-коллекции или массива.

    <Элемент> - объект (переменная), совпадающий по классу с элементами коллекции, или имеющий тип Variant. Для массивов допустим только тип Variant. Нормально цикл заканчивается, когда переменная цикла получила все возможные значения и коллекция исчерпана. Но можно организовать досрочный выход. Для этого используется внутренняя конструкция Exit For. Обычно она помещается в Then -ветвь оператора If. Если условие выхода выполняется, следом выполняются Exit For и следующие за ним операторы, требуемые для корректного завершения цикла. После чего управление покидает цикл.

    Цикл For Each не может использоваться для массивов с элементами, определенными пользователем. Последнее объясняется тем, что переменная типа Variant не может принимать пользовательский тип.

    Приведем пример использования "старой" и "новой" конструкций:

    With Documents
    	For i = 1 To .Count		For Each doc In Documents
    		Debug.Print 	.Item(i)		Debug.Print 	doc
    	Next i 				Next doc
    End With

    Преимущество "новой" очевидно: удобнее иметь сам элемент doc вместо индекса элемента i. Особенно это может быть важно, когда в ходе цикла приходится многократно обращаться к элементу doc.

    При работе с коллекциями используйте, как правило, конструкцию For Each. Кроме всего прочего, она выполняется намного эффективнее по времени исполнения.

    Объекты Range

    Роль коллекций во всех приложениях Office 2000 велика. Если одновременно могут существовать несколько объектов (экземпляров) одного и того же класса, то существует и объединяющий их класс - коллекция, в которой собраны все экземпляры. Класс коллекция позволяет работать с последовательностью элементов - экземпляров класса.

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

    Что определяет объект Range?

    Пусть задана коллекция элементов - последовательность индексированных элементов. Индексы (ключи) элементов задают порядок их расположения в коллекции. Индексы могут быть как числами, так и именами. Объект Range позволяет задать произвольный диапазон этой последовательности, для чего достаточно задать индексы первого и последнего элемента. Диапазон может быть стянут в точку, так что объект Range может определять единственный элемент, а в приложении Word и пустой элемент - точку вставки. Используя свойства и методы объекта Range, можно выполнять групповые операции над всеми элементами диапазона. В одном из предыдущих примеров встречаются строки, использующие объект Range в Excel:

    xlApp.Range("A1:A2") = 2
    xlApp.Range("B1") = "=A1+A2"
    xlApp.Range("B2") = "=A1*A2"

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

    Метод Range

    Ранее мы говорили, что объект класса Paragraph имеет свойство Range, иначе говоря, в него вложен объект Range., задающий последовательность символов данного абзаца. Объектов, имеющих свойство Range, немало. Это понятно, ведь не только с абзацами полезно связать диапазон, соответствующий объекту. При обращении к свойству Range таких объектов в качестве результата получаем соответствующий диапазон - ссылку на объект Range.

    В ряде случаев можно определить новый объект класса Range, используя метод Range. Заметьте: метод, а не свойство. Так объекты более высокой иерархии, например объект класса Document, имеют метод Range и не имеют соответствующего свойства. Синтаксис метода таков:

    Function Range(Start, End) As Range

    Он имеет два параметра: Start и End - и возвращает как результат объект класса Range.

    Если объект Range уже построен, то значения его параметров Start и End можно переопределить, вызвав его метод SetRange, в котором можно задать новые значения этих параметров.

    В следующем примере работы с документом Word демонстрируется как применение свойства Range, так и метода Range. В нем же показано и применение метода SetRange.

    Public Sub WorkWithRange()
    Dim myr As Range, myr1 As Range
    Dim i As Byte
    'Добавляем новый документ
    Documents.Add
    With ActiveDocument
    'Добавляем 7 абзацев в текст созданного документа
        For i = 1 To 7
            .Paragraphs.Last.Range.Text = "Абзац "  i
            .Paragraphs.Add
        Next i
    'Используется свойство Range
        Set myr = .Paragraphs(1).Range
    'Выделен первый абзац
        myr.Select
    'Новый объект myr1 задает пустой объект - позицию курсора
    'В правой части вызывается метод Range
        Set myr1 = ActiveDocument.Range(Start:=myr.Start, End:=myr.Start)
        myr1.Select
    'Теперь объект myr1 задает единственный символ -первый символ текста
    'Здеесь использован метод SetRange
        myr1.SetRange Start:=myr1.Start, End:=myr1.End + 1
        myr1.Select
    'Три абзаца с третьего по пятый выделяются курсивом
        myr1.SetRange Start:=.Paragraphs(3).Range.Start, End:=.Paragraphs(5).Range.End
        myr1.Font.Italic = True
        myr1.Select
    End With
    End Sub

    Объекты Selection

    Еще один общеупотребительный объект - Selection. Как и Range, этот объект присутствует в большинстве приложений Office 2000. Он задает выделенную область документа Word, рабочего листа Excel, область в окне презентации. Его особенность в том, что в каждом окне (точнее, в каждом подокне) может существовать только один объект Selection. Каждое новое выделение некоторой области в подокне отменяет или модифицирует старое. Этим он отличается от объектов Range, несколько экземпляров которых могут существовать одновременно. Selection, как и объект Range, задает непрерывную область элементов. Но есть и принципиальное отличие: объект Selection не является диапазоном, заданным своим началом и концом, - это некоторая область, например таблица или ее столбец.

    Но объекты Selection и Range имеют и много общего. Прежде всего, оба предназначены для того, чтобы задавать некоторую область элементов, и позволяют выполнять действия над элементами этой области. Возможности этих объектов для работы с элементами области примерно одинаковы. Так, у приложения Word свойства и методы данных классов объектов совпадают на 90%. Вот почему почти каждую задачу, которую можно решить в терминах объекта Selection, можно решить и в терминах объекта Range. Macrorecorder (о нем еще будет подробный разговор) любит использовать объект Selection в своей работе, и очень часто программист "подправляет" программу, переписывая ее для повышения эффективности в терминах свойств и методов объекта Range.

    Отметим еще одну связь (ее можно назвать двойственностью) между этой парой объектов. У объекта Range есть метод Select, который выделяет заданный диапазон, создавая объект Selection, после чего можно использовать свойства и методы этого объекта. Также и объект Selection имеет метод Range, который определяет диапазон, связанный с областью выделения, после чего можно работать с этим диапазоном, используя свойства и методы объекта Range. Перепишем наш пример, где использовался объект Range, задействовав объект Selection:

    Public Sub WorkWithSelection()
    Dim myr As Range
    Dim i As Byte
    'Добавляем новый документ
    Documents.Add
    With ActiveDocument
    'Добавляем 7 абзацев в текст созданного документа
        For i = 1 To 7
            .Paragraphs.Last.Range.Text = "Абзац "  i
            .Paragraphs.Add
        Next i
    'Используется свойство Range
        Set myr = .Paragraphs(1).Range
    'Выделен первый абзац. Создаем объект Selection
        myr.Select
    'Действия с объектом Selection
    'Стягивание в начало абзаца - точку вставки
        Selection.MoveLeft
    'Расширение на один абзац вправо, снова выделяя первый абзац
        Selection.MoveDown Unit:=wdParagraph, Count:=1, Extend:=wdExtend
    'Передвинемся к началу третьего абзаца
        Selection.Move Unit:=wdParagraph, Count:=2
    'Три абзаца с третьего по пятый выделяются курсивом
        Selection.MoveDown Unit:=wdParagraph, Count:=3, Extend:=wdExtend
        Selection.Font.Italic = True
    End With
    End Sub

    Первоначально объект Selection создается как результат вызова метода Select объекта Range. После этого можно работать с этим объектом. При изменении диапазона объекта Selection приходится работать не с параметрами Start и End, как это делается для объектов Range, а использовать специальные методы Move, часть из которых мы применили в нашем примере. Вот их краткое описание:

  • метод MoveLeft сжимает область выделения до точки и передвигает ее в начало диапазона. В примере точка вставки перемещается к началу первого абзаца;
  • метод Move сжимает область выделения до точки и передвигает ее в нужное место. В примере точка вставки перемещается на два абзаца;
  • метод MoveDown расширяет область выделения. Параметр Unit указывает единицы, в которых ведется отсчет при расширении области (у нас - в абзацах); параметр Count задает число этих единиц. Параметр Extend указывает, нужно ли расширение или перемещение области, сжатой в точку вставки.
  • Метод Select и свойство Selection

    Рассматривая в приложении Word объект Range, мы видели, что он может быть получен как результат вызова метода Range объектов одних классов и свойства Range объектов других классов. Свойством Range обладают объекты более низких уровней иерархии - коллекции слов и ячеек, абзацы и строки. Считается, что в каждый такой объект вложен объект Range, задающий диапазон, связанный с объектом. При вызове свойства этот существующий объект возвращается, и с ним можно работать. У объектов верхнего уровня иерархии: Application, Windows - встроенного диапазона нет, но зато есть метод Range, позволяющий создать новый объект этого класса.

    С объектом Selection ситуация аналогична. И здесь свойство Selection возвращает уже существующий объект, а метод Select позволяет создать новый объект. Но здесь ситуация двойственна - объекты, имеющие свойство Range, обладают методом Select и, наоборот, объекты верхнего уровня иерархии имеют свойство Selection. Объяснение очевидно: объект Selection существует в единственном экземпляре в каждом подокне, и поэтому объекты более низких уровней иерархии просто не могут иметь встроенное свойство Selection. Им могут обладать только объекты класса Pane (подокно), Windows и Application.

    Рассмотрим синтаксис метода Select:

  • Sub Select()
  • Sub Select([Replace])
  • В первом случае создается новая область выделения - объект Selection, во втором - область выделения можно расширить или заменить в зависимости от значения параметра Replace. Заметьте: метод Select реализован не как функция, явно возвращающая результат, а как процедура ( Sub ), которая объекта Selection не возвращает. Создание этого объекта - результат побочного эффекта этой процедуры. Созданный объект связывается с объектами верхнего уровня иерархии: окном и приложением. Его можно получить, обратившись к глобальному свойству Selection. Но Вы не можете получить ссылку на этот объект, а, следовательно, не можете создать переменную этого класса, так, как это могли делать при работе с объектами класса Range (вспомните переменную MyRange из наших примеров). Это предохраняет нас от соблазна "обмануть систему" и иметь две переменные - два объекта Selection одновременно.

    Типичный и правильный способ работы с объектом Selection таков:

  • Создается или выбирается объект, область которого должна быть выделена.
  • Для этого объекта вызывается метод Select, возвращающий в качестве результата объект Selection.
  • Проводится работа с объектом Selection в области выделения.
  • Если нужно перейти к новой области выделения, то либо область выделения перемещается (как в нашем примере), либо повторяются действия, начиная с первого пункта.
  • Рассмотрим пример, в котором пользователь переключается между двумя областями выделения

    Sub WorkWithTwoReg()
    'Переключение между двумя областями выделения документа
    'Создание двух областей
    Dim myRange1 As Range
    Dim myRange2 As Range
    Dim i As Byte
    Dim Answer As Variant ' Выбор пользователя
    'Добавляем новый документ
    Documents.Add
    With ActiveDocument
    'Добавляем 7 абзацев в текст созданного документа
        For i = 1 To 7
            .Paragraphs.Last.Range.Text = "Абзац "  i
            .Paragraphs.Add
        Next i
        Set myRange1 = .Range(Start:=.Paragraphs(2).Range.Start, _
            End:=.Paragraphs(3).Range.End)
        
        Set myRange2 = .Range(Start:=.Paragraphs(6).Range.Start, _
            End:=.Paragraphs(7).Range.End)
        Answer = InputBox(prompt:=" Выберите область выделения (1/2)", _
                Default:=1)
        If Answer = 1 Then
            myRange1.Select
            'Макрос ItInSel работает с первой выделенной областью
            ItInSel
        Else
            myRange2.Select
            'Макрос ItInSel работает со второй выделенной областью
            ItInSel
        End If
    End With
    
    End Sub

    В этом макросе почти все применяемые средства хорошо знакомы. До сих пор мы не пользовались только стандартным для Visual Basic методом InputBox, который открывает диалоговое окно, позволяющее принять ввод пользователя. Заметьте, что работу в выделенной области осуществляет процедура ItInSel. Ее можно было сделать довольно сложной, но мы ограничились одним оператором:

    Public Sub ItInSel()
    Selection.Font.Italic = True
    End Sub

    Анализируя этот макрос, обратите внимание на два обстоятельства:

  • Если мы хотим постоянно работать с некоторыми областями, имеет смысл создать соответствующие им объекты. "Хранителями" областей выступают объекты класса Range В нашем примере это переменные myRange1 и myRange2. Объекты Selection появляются в последнюю минуту, когда область нужно выделить и начать с ней работать.
  • Работа с объектом Selection может быть предпочтительнее, так как явные ссылки заменяются косвенными. Это позволяет создать процедуру, не зависимую от области. Подобную ситуацию демонстрирует вызов процедуры ItInSel.
  • Активные объекты и метод Activate

    Объект Selection является примером косвенной адресации. Он задает некоторую выделенную область, и его свойства и методы позволяют изменять состояние этой области. Другой пример косвенной адресации - активные элементы. Как в подокне может быть только один выделенный элемент, так и активный элемент может быть единственным в своем классе - одно активное окно, один активный документ или рабочий лист. Обычно активный элемент находится в фокусе клавиатуры, именно ему направлен ввод пользователя. Сделав активным новый элемент, мы отменяем, деактивируем элемент, ранее находившийся в фокусе клавиатуры.

    Метод Activate делает активным элемент, его вызвавший. Этим методом обладают элементы верхних уровней иерархии: Application, Window, Pane, Document, WorkBook, Worksheet, Chart и др. В приложениях Word и PowerPoint эти объекты обладают также булевым свойством Active, имеющим статус "только для чтения". При активизации объекта свойство Active получает значение True, при деактивации - False. Значение свойства позволяет понять, в каком состоянии находится тот или иной объект этих приложений.

    Чтобы обратиться к выделенному объекту, достаточно иметь одно глобальное свойство Selection, поскольку в каждый текущий момент существует только один выделенный элемент. Активных элементов одновременно существует несколько, по одному в каждом классе. Поэтому для обращения к активному элементу надо указывать его класс. Поэтому для каждого класса имеется свое глобальное свойство. Чтобы обратиться к активному элементу некоторого класса Z, нужно вызвать соответствующее глобальное свойство ActiveZ, например ActiveDocument или ActiveWindow. В наших примерах мы неоднократно уже использовали обращение к активному документу - ActiveDocument. Рассмотрим еще один пример, в котором пользователь в приложении Excel выбирает рабочий лист. В зависимости от его выбора активизируется указанный лист, и в двух первых ячейках появляется приветствие, текст которого также зависит от выбора пользователя:

    Public Sub Actis()
    Dim Answer As Integer
    Answer = InputBox(Prompt:="Выберите номер страницы для Вашей работы(1/2/3)", _ Default:=1)
    'Активизирует рабочий лист, выбранный пользователем
    ActiveWorkbook.Sheets(Answer).Activate
    'Работа с активным листом
    ActiveSheet.Cells(1, 1) = "Привет,"
    Select Case Answer
    Case 1: ActiveSheet.Cells(1, 2) = "Михаил!"
    Case 2: ActiveSheet.Cells(1, 2) = "Владимир!"
    Case Else: ActiveSheet.Cells(1, 2) = "Люди!"
    End Select
    End Sub

    На этом мы заканчиваем первое знакомство с общеупотребительными объектами Office 2000. В заключение мы хотим рассказать уже не о каких-либо конкретных объектах, а об удивительном программном средстве, позволяющем работать с ними. Речь пойдет о Macrorecorder.

    Macrorecorder

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

    Так возникает двойственность. Одни и те же вещи можно сделать и визуально, и программно - эффект будет один. Большинство приложений Office 2000, и в первую очередь Word и Excel, рассчитаны на визуальный способ работы с ними. Но программистов не обманешь - они-то знают, что всякий раз, когда пользователь визуально инициирует действие, вызывается программа, выполняющая это действие. Дело в том, что система следит за действиями пользователя, анализирует их и запускает программы, соответствующие этим действиям. Иначе говоря, происходит трансляция с языка действий в язык программирования. Поскольку этот язык объектный, то можно говорить, что действия пользователя (события) интерпретируются и приводят к вызову методов и изменению свойств в мире объектов. Поскольку есть интепретатор действий, то можно построить и транслятор.

    Macrorecorder - это и есть транслятор. Всякий раз, когда пользователь запускает Macrorecorder, создается программа (макрос) на языке VBA, которая является результатом трансляции действий пользователя с момента запуска Macrorecorder до момента окончания записи макроса. Пользователь оперирует с образами объектов на экране, программа - с объектами Office 2000. Заметьте: одного и того же эффекта, пользователь иногда может достичь разными путями - он может вызвать команду меню или щелкнуть соответствующую кнопку или нажать комбинацию "горячих" клавиш. С этими разными событиями может связываться одна и та же процедура обработки. Поэтому созданная Macrorecorder программа в таких случаях будет одинаковой, не зависящей от того, как пользователь добился нужного ему эффекта.

    На сегодня Macrorecorder не очень "интеллектуален" - он слепо копирует действия пользователя и не занимается оптимизацией созданной им программы. Так, если пользователь записал в ячейку А1 число 15, в А2 - 17, а потом передумал и решил вернуться к ячейке А1 и заменить 15 на 21, то Macrorecorder в программе повторит все его действия. "Любимый" объект Macrorecorder - Selection, и это понятно: всякий раз, когда пользователь выбирает новый объект, Macrorecorder создает новый объект Selection. Сегодня типична ситуация, когда программист использует макрос, созданный Macrorecorder, как заготовку, оптимизируя код вручную. Думается, интеллект Macrorecorder повысится в следующих версиях. Но и сейчас это крайне полезное средство. Office 2000 позволяет чрезвычайно просто решить вручную массу задач (в этом вся его суть). Вместе с тем необходимость в решении таких задач может возникать неоднократно, и потому полезно иметь соответствующую программу. Так что технология такова: один раз задача решается вручную, Macrorecorder создает макрос, транслируя наши действия, затем макрос, если надо, оптимизируется и запускается всякий раз, когда возникает необходимость решения данной задачи.

    Завершим описание примером. Наиболее удобен для демонстрации Excel, - именно здесь вручную можно решать очень необычные задачи. Поэтому и Macrorecorder интенсивнее всего используется в Excel. Хотя, привыкнув, Вы будете применять его и в других приложениях Office 2000. Рассмотрим написание в Excel программы, создающей последовательность первых N чисел Фибоначчи, - типичная задача для студентов первого курса, изучающих программирование. В ней есть рекуррентные соотношения, цикл, она требует понимания понятия "переменная". Рекуррентные соотношения для получения чисел Фибоначчи таковы:

    A1 = 1;	A2 = 2;		A k= A k-1 + A k-2; 	k = 3…N;
    (рис 1.11)

    Вот как мы решали эту задачу вручную ( рис. 1.11). Вначале вызвали Macrorecorder, выбрав в меню Tools пункт Macro, затем - Record New Macro (проще щелкнуть кнопку начала записи макроса, если она есть на панели). В появившемся диалоговом окне задали имя макроса - Fibonachi. Заметьте: появляется кнопка окончания записи макроса, если ее не было на соответствующей панели. Теперь наши дальнейшие действия будут транслироваться в соответствующую программу. В ячейку А1 мы записали текст " Числа Фибоначчи ", в ячейки А2 и А3 - числа 1 и 2, в ячейку А4 - формулу " = А2+А3 ", а затем скопировали эту формулу до ячейки А20 включительно. По ходу копирования формула пересчитывалась, и в ячейках появлялись значения, соответствующих чисел Фибоначчи. Затем мы, щелкнув кнопку, выключили запись макроса. Результаты действий - на рис. 1.7. Созданный Macrorecorder макрос Fibonachi теперь доступен, и его можно вызывать в любой момент. Вот его текст:

    Sub Fibonachi()
    '
    ' Fibonachi Macro
    ' Macro recorded 28.02.1999 by Vladimir Billig
    
        Selection.Font.Bold = True
        ActiveCell.FormulaR1C1 = "Числа Фибоначчи"
        Range("A2").Select
        ActiveCell.FormulaR1C1 = "1"
        Range("A3").Select
        ActiveCell.FormulaR1C1 = "2"
        Range("A4").Select
        ActiveCell.FormulaR1C1 = "=R[-2]C+R[-1]C"
        Selection.AutoFill Destination:=Range("A4:A20"), Type:=xlFillDefault
        Range("A4:A20").Select
    End Sub

    В созданном макросе используются уже известные нам объекты: Range, Selection, ActiveCell и метод Select объекта Range. В комментариях нуждается свойство ячеек Excel - FormulaR1C1, - позволяющее связать с ячейкой значение или формулу (для ячейки А4 ), заданную в относительных координатах R ( Row - строка) и C ( Column - столбец). Отсчет координат ведется от активной ячейки, поэтому для ячейки А4 формула " =А2 +А3 " в этих координатах принимает вид: " =R[-2]C+R[-1]C ". Основная операция копирования не потребовала организации цикла в программе. Этот цикл реализован внутри метода AutoFill, вызванного для объекта Selection. Два параметра этого метода Destination и Type задают область и тип копирования. В оптимизации этот макрос не нуждается

    Ранее мы говорили, что браузер объектов - это Ваш неизменный спутник и помощник в процессе программистской работы. Другим таким же полезным помощником является Macrorecoder!

    Дело даже не в том, чтобы получить макрос для многократного использования, - Вы и сами его можете написать. Но часто возникает ситуация, когда Macrorecoder запускается для того, чтобы понять, какие объекты и какие методы следует использовать для решения той или иной задачи. Например, Вы могли бы не знать, как скопировать формулу в соседние ячейки, чтобы она корректно изменилась при копировании. Макрос Fibonachi подсказал бы Вам, что для этого следует использовать метод AutoFill. Заодно Вы бы поняли, что в область копирования ( destination ) должен быть включен и источник копирования. Так что не забывайте Macrorecoder - это Ваше подручное средство.

    На этом мы заканчиваем предварительное знакомство с объектами Office 2000 и переходим к систематическому изучению самого языка программирования VBA.

    Вернуться к учебному плану