Библиотека: А. Горев, С. Макашарипов, Р. Ахаян. Эффективная работа с СУБД

Глава 10
Использование готовых компонентов в приложении
10.1. Основные преимущества модульного проектирования прикладных программ
10.2. Как правильно использовать OLE 2.0
Возможности OLE 2.0
Использование OLE Automation
Управление объектами Excel
Управление объектами Word for Windows
10.3. Использование OLE Automation для передачи данных
Построение графиков с помощью MS Graph 5.0
Построение графиков с помощью MS Excel 7.0
Построение отчета в Word for Windows
Запись информации в Schedule+
10.4. Применяем ActiveX
Иерархический список
Календарь

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

10.1. Основные преимущества модульного проектирования прикладных программ

    В условиях жесткой конкуренции на рынке стандартного и заказного программного обеспечения большое значение имеет умение программиста предложить заказчику решение, которое позволит организации максимально быстро повысить эффективность и производительность ее работы.
    В этом параграфе мы расскажем о том, какие возможности дает среда Windows для решения поставленной в предыдущем абзаце цели и постараемся убедить вас в эффективности модульного проектирования пользовательского приложения.
    Одно из наиболее часто используемых решений - ориентировка на заказные прикладные программы, которые дают конечным пользователям наилучший доступ к информации с учетом всех особенностей работы данного заказчика. Однако создание заказных прикладных программ может быть очень дорогостоящим и наверняка потребует больших затрат времени. К тому же, в соответствии с развитием организации или какими-то изменениями в профиле ее действия, заказное программное обеспечение придется постоянно корректировать. Если посмотреть на заказную прикладную программу с точки зрения выполнения ею отдельных функций, то окажется, что значительная часть поддерживаемых ею функций, таких как редактирование данных, выполнение расчетов и т. п., достаточно стандартны и могут быть легко выполнены с помощью стандартного программного обеспечения. Использование функциональных возможностей, доступных в существующих прикладных программах, может существенно ускорить и удешевить процесс автоматизации обработки данных.
    Например, прикладная программа, которая ищет с помощью системы управления базой данных сведения о потенциальных клиентах, может использовать возможности текстового процессора Microsoft Word for Windows для подготовки рекламных писем. Это решение позволяет использовать существующие функциональные возможности прикладных программ Microsoft Office, освобождая вас от необходимости разрабатывать всю прикладную программу.
    Помимо несомненного выигрыша по времени, использование существующих прикладных программ в формировании заказных решений стимулируют следующие тенденции:

  • Быстрое повышение мощности и снижение стоимости персональных компьютеров.
  • Поистине революционные масштабы объединения вычислительных и информационных возможностей в рамках локальных и глобальных компьютерных сетей.
  • Высокие требования пользователей к качеству пользовательского интерфейса. Для персонального компьютера графический пользовательский интерфейс стал в настоящее время стандартом де-факто.

    Далее в этом и последующих параграфах данной главы мы рассмотрим наиболее важные аспекты, связанные с использованием функциональных возможностей Microsoft Office в прикладной программе для автоматизации обработки данных. Но сначала мы остановимся на тех средствах, которые составляют основу использования стандартного прикладного программного обеспечения в разрабатываемых пользовательских приложениях.
    Стандартные прикладные программы Microsoft Office могут быть источником большого числа программных модулей (объектов) и составной частью инструментальных средств разработки благодаря функциональным возможностям стандарта OLE 2.0 и языка программирования Microsoft Visual Basic for Application. Это означает, что прикладные программы Microsoft Office содержат компоненты, которые вы можете использовать при разработке пользовательского приложения. Вы и пользователи ваших программ получаете тем самым следующие существенные преимущества:

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

    Использование стандарта OLE 2.0 является основой для разработки компонентного программного обеспечения, потому что этот стандарт обеспечивает средства для определения объектов и их совместного использования различными программами. Например, табличный процессор Microsoft Excel - одна из первых прикладных программ, которая предоставляет богатый набор объектов OLE. Библиотека объектных модулей OLE Microsoft Excel включает свыше 120 объектов и около 2700 связанных с ними методов и свойств. Эти объекты доступны через любую прикладную программу или язык, который поддерживает стандарт OLE 2.0, и их использование позволяет воспользоваться всеми функциональными возможностями Microsoft Excel без необходимости обеспечения этой функциональности в своей прикладной программе.

10.2. Как правильно использовать OLE 2.0

    Стандарт OLE - Object Linked and Embedding (связывание и внедрение объектов) собственно своим названием определяет, что речь в нем идет о компоновке объектов и правилах их совместного использования для достижения интеграции среди прикладных программ. Представляя изображения, диаграммы, таблицы, фрагменты речи, документы и другие функциональные единицы программы как объекты, пользователи могут с большей легкостью объединять и обрабатывать данные из разных прикладных программ.
    В этом параграфе мы изучим:

  • основные преимущества использования технологии OLE;
  • методику создания и использования OLE-объектов;
  • принципы работы OLE Automation.

    Какие преимущества дает пользователю и разработчику эта технология? Вот основные из них:

  • Редактирование на месте позволяет работать с документом другого приложения Windows, не покидая пользовательского приложения. Необходимые элементы управления, включая меню, появятся на месте текущих, а после завершения работы вернутся на свое место элементы управления и меню пользовательского приложения. Это позволяет избежать необходимости ручной загрузки и перехода в другое приложение.
  • Перетаскивание данных между приложениями помогает реализовать наиболее естественный для пользователя метод сбора различных данных для использования в одном документе.
  • Технологии встраивания и связывания объектов дают возможность выбрать наиболее эффективный способ объединения разнородных данных в одном документе. При этом связывание позволяет не увеличивать без необходимости объем документа и использовать наиболее свежую версию данных, хранящуюся в отдельном файле. Встраивание обеспечивает хранение всех необходимых данных в одном приложении.
  • Поддержка вложенных объектов позволяет в одном документе держать несколько зависимых объектов без необходимости обращения к нескольким приложениям. Например, встроенная в форму электронная таблица Excel может содержать встроенную в таблицу диаграмму. Изменения в электронной таблице повлекут изменения в диаграмме.
  • OLE Automation позволяет в приложении программным путем устанавливать свойства и задавать команды для объектов другого приложения. Это дает большие возможности для управления процессом подготовки текстовых документов высокого качества, формирования графиков или выполнения расчетов.

Возможности OLE 2.0


Стандарт OLE 2.0 описывает правила интеграции прикладных программ.

    Он фактически расширяет пользовательский интерфейс, делая его более интуитивно понятным. Стандарт OLE 2.0 не ставит пользователя перед необходимостью набора команд или выбора опций, предоставляя возможность выполнять работу более естественным способом, управляя объектами в интерактивном режиме на экране компьютера. Пользователь, вместо того чтобы изучать методы работы с прикладный программой или операционной системой, может сосредоточиться на более эффективной работе с данными и документами.
    Технология OLE 2.0 особенно полезна потому, что устанавливает стандартный метод взаимодействия между прикладными программами при использовании различных объектов (документов, подготовленных разными прикладными программами). Она предлагает мощные средства для создания документов, получающих данные из разнообразных источников информации. Такие документы называются составными документами. Объекты, которые они содержат, могут включать почти любой тип информации, в том числе текст, растровые изображения, иллюстрации и фрагменты речи.
    В технологии OLE 2.0 выделяются два главных типа данных, связанных с объектом: данные представления и локальные данные.


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

    Используя OLE 2.0 пользователь может также связывать или включать объект в документ.


Связывание - это процесс, при котором в документ будут помещены только данные представления объекта и ссылка (или указатель на местонахождение) на локальные данные.

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


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

    Вся информация, необходимая для редактирования объекта, содержится в документе. Любой объект, который содержит другие объекты (как связанные, так и вложенные), называется контейнером. Контейнерами чаще всего являются составные документы.
    Включение объектов хотя и увеличивает объем документа, но позволяет перемещать объект наряду с документом на другой компьютер и тем самым редактировать такие объекты на различных рабочих местах. Связанные объекты не могут "путешествовать" с документами за пределы локальной файловой системы компьютера, но они более эффективны, чем вложенные объекты, потому что один образец локальных данных объекта может служить источником для большого числа различных документов.

Использование OLE Automation


Один из важнейших элементов стандарта OLE 2.0 - OLE Automation - определяет способ управления командами прикладной программы из другой прикладной программы.

    Прикладные программы, поддерживающие OLE Automation, имеют соответствующие объекты, которые так и называются - объекты OLE Automation, посредством которых вы можете управлять работой всех остальных объектов прикладной программы, используя возможности Visual Basic for Application.
    OLE Automation для управления объектами использует OLE-серверы.


OLE-сервер - это программа, которая может предоставить другим программам возможность использовать свои объекты.

Программы, которые могут управлять объектами OLE-серверов, называются OLE-клиенты или OLE-контроллеры.

    Например, в версии 3.0 Visual FoxPro может выполнять функции только OLE-контроллера. Мы можем управлять объектами OLE-сервера, но не можем предоставить в чье-либо управление объекты Visual FoxPro.
    Большинство OLE-серверов являются так называемыми серверами Out-of-Process. Они являются исполняемыми программами и могут взаимодействовать как с 16-bit, так и с 32-bit OLE-контроллерами. Расплатой за это является невысокая скорость обмена данными и значительные потребляемые ресурсы памяти. Другой тип OLE-сервера называется In-Process и представляет собой DLL-библиотеку, которая динамически подгружается и выгружается по необходимости. Хорошим примером такого сервера является процессор баз данных СУБД Access 7.0. Обмен данными с этим типом OLE-сервера происходит значительно быстрее, но работать он может только с OLE-контроллером такой же разрядности.
    В табл. 10.1 приводится важная для разработчика информация о некоторых OLE-серверах Microsoft.

Таблица 10.1. OLE-серверы Microsoft
OLE-серверГде найти информацию об объектах
Серверы Out-of-Process
Microsoft Schedule+ 7.0-
Microsoft Graph 5.0VBA_GRP.HLP
Microsoft Word 7.0WRDBASIC.HLP
Microsoft Excel 7.0VBA_XL.HLP
Cерверы In-Process
Data Access ObjectDAO.HLP, DAOSDK.HLP
SQL Distributed Management ObjectsSQLBOOKS.MVB

    В качестве примера приведем несколько OLE-объектов для Microsoft Excel:

  • Application - запускает программу Microsoft Excel;
  • Workbook - рабочая книга, которая включает отдельные листы - один файл формата Microsoft Excel;
  • Chart - график в рабочей книге;
  • Worksheet - рабочий лист в книге;
  • Range - одна ячейка или диапазон ячеек на листе.

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

Application.Quit

    Объект Application включает в себя большое количество других объектов. Например, вы можете использовать следующую команду для ссылки на текущую рабочую книгу, открытую в Microsoft Excel:

Application.Workbooks

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


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

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

* Организуем ссылку на запущенное приложение
oExlApp = GETOBJECT(,"Excel.Application")
nWrk = 1
* Определяем, сколько открыто рабочих книг
nCount = oExlApp.Application.WorkBooks.Count
FOR nWrk = 1 TO nCount
     * Выведем наименование каждой рабочей книги
? oExlApp.Application.WorkBooks.Item(nWrk).FullName
NEXT
* Закроем приложение
oExlApp.Application.Quit

    Чтобы запустить этот пример, загрузите Excel, откройте несколько файлов. В Visual FoxPro наберите приведенный в примере код в программном файле. В окне Command сделать это нельзя из-за команды FOR, которая не поддерживается в интерактивном режиме командного окна. Вам также может показаться, что в этом фрагменте лишней является переменная nCount. Это не так! При использовании OLE Automation не встраивайте ее код внутрь команд Visual FoxPro. Запустите программный файл.
    Как вы могли заметить из приведенного примера, для ссылки на одну рабочую книгу в коллекции мы применяли метод Item, в котором используется номер элемента коллекции. Для ссылки на первую рабочую книгу в коллекции укажите:

Application.Workbooks.Item(1)
    Для того чтобы закрыть первую книгу в коллекции:
Application.Workbooks.Item(1).Close

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

Application.Workbooks.Item(1).Worksheets.Item("Sheet1").Cells.Item(1,1)

    Как видно из приведенных примеров, мы должны разбираться в коллекциях для того, чтобы иметь возможность спускаться "вниз" по иерархии объектов. На рис. 10.1 приведена схема такого перемещения между объектами Microsoft Excel.


Рис. 10.1. Перемещение вниз по иерархии объектов с помощью коллекций в Microsoft Excel

    Принцип перемещения вверх по иерархии более привычен для программиста, освоившего объектно-ориентированное программирование. Для этого используется свойство Parent и пока отсутствующее в Visual FoxPro, но привычное для приложений Microsoft Office свойство Application. Соответствующая схема для использования этих свойств приведена на рис. 10.2.


Рис. 10.2.

    При использовании OLE Automation очень важным понятием является понятие объектов верхнего уровня.


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

    Имеющиеся, например, в Microsoft Excel объекты верхнего уровня представлены на рис. 10.3.


Рис. 10.3.

    Несколько ранее вы, наверное, уже обратили внимание, что ссылка на вновь создаваемый объект OLE Automation в программе Visual FoxPro выполняется так же, как при не визуальном программировании на новый объект самого Visual FoxPro - с помощью функции

CREATEOBJECT(ClassName [, eParameter1, eParameter2, ...])

    Если OLE-объект уже существует, получить на него ссылку можно с помощью функции

GETOBJECT([FileName ][, ClassName])

    Параметр FileName позволяет указать имя существующего файла (и при необходимости путь к нему), содержащего OLE-объект, который необходимо активизировать. С помощью параметра ClassName можно указать имя объекта верхнего уровня (класс OLE-объекта). Это необходимо в том случае, если, как мы это показали на примере Microsoft Excel, в приложении в одном файле может храниться несколько объектов верхнего уровня, например таблицы, графики и т. д. В данном случае для параметра должен использоваться следующий синтаксис:

<<"Имя приложения">>.<<"Имя объекта верхнего уровня">>
    Например:
oSht = GETOBJECT("C:\VFP\SAMPLE\VAT.XLS","EXCEL.SHEET")

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

` В первом примере создаем объект MS Excel
Dim oExlApp As Object
' Объявляем переменную для ссылки на объект
Set oExlApp = CreateObject("Excel.Application")
` Создаем объект
oExlApp.Visible = True ' Выводим объект на экран
...
oExlApp.Quit ' После окончания работы закрываем Excel
Set oExlApp = Nothing ' Стираем ссылку на объект из памяти
` Во втором примере ссылаемся на объект MS Excel
Dim oExlApp As Object
Set oExlApp = GetObject("C:\VFP\SAMPLE\VAT.XLS","Excel.Sheet")
...
Set oExlApp = Nothing

Управление объектами Excel

    Для того чтобы остановиться на проблемах взаимодействия пользовательского приложения с объектами Excel, нам придется более подробно обсудить специфические в данном случае особенности работы функций CREATEOBJECT() и GETOBJECT(). Поэтому систематизируем необходимые данные для важнейших объектов верхнего уровня Microsoft Excel и приведем их в табл. 10.2.

Таблица 10.2. Поведение объектов верхнего уровня Microsoft Excel
ОбъектФункцияОписание поведения
ApplicationCreateObjectВсегда запускает невидимую копию Microsoft Excel. Файл рабочей книги не загружается.
GetObjectЕсли параметр FileName представляет собой пустую строку, запускается новая невидимая копия Microsoft Excel без загрузки файла рабочей книги. Если параметр пропущен, то предпринимается попытка получить ссылку на уже запущенную копию Microsoft Excel и в случае неудачи генерируется ошибка. Не указывайте в параметре FileName имя файла. Для этого случая используйте объекты Sheet или Chart.
Sheet или ChartCreateObjectЕсли не существует запущенной копии Microsoft Excel, то запускается невидимая копия и создается рабочая книга с именем "Object" и один рабочий лист с именем "Sheet1". Для объекта Chart помимо этого создается еще один рабочий лист с именем "Chart1". Как только ссылка на созданный объект перестает существовать (стирается), рабочая книга удаляется, но Excel остается загруженным в памяти компьютера. Если одна или несколько копий Microsoft Excel уже запущены, то добавляется рабочая книга с параметрами, как это было описано в предыдущем абзаце. В случае, когда уже работает несколько копий Excel, предугадать, в какой из них будет добавлена таблица, невозможно.
GetObjectЕсли параметр FileName является допустимым (существующим) именем файла и Microsoft Excel не запущен, то запускается новая невидимая его копия с невидимой рабочей книгой. Если хотя бы одна копия Microsoft Excel уже запущена, рабочая книга открывается в ней. При этом будет получена ошибка, если указанное в функции имя файла совпадет с уже открытым файлом в загруженной копии Excel. Если параметр FileName задан в виде пустой строки ("") и если не существует запущенной копии Microsoft Excel, то запускается невидимая ее копия и создается рабочая книга с именем "Object" и один рабочий лист с именем "Sheet1". Если параметр FileName задан в виде пустой строки ("") и если хотя бы одна копия Microsoft Excel загружена в память, то в одной из них открывается рабочая книга, как это было описано выше. Если параметр FileName не указан, всегда генерируется ошибка.

    Как вы можете заметить, изучив табл. 10.2, создание объектов OLE Automation или обращение к ним в Microsoft Excel зачастую может привести к совершенно различным последствиям. Почти всегда Excel создает невидимую копию приложения. Для того чтобы сделать ее видимой для пользователя, надо присвоить свойству Visible объекта Application значение "истина":

...Application.Visible = .T.

    Если создается невидимая копия рабочей книги, то сделать ее видимой можно, присвоив значение "истина" свойству Visible окна:

...Window(n).Visible = .T.

    В некоторых случаях Excel при запуске посредством OLE Automation не открывает новый файл. Тогда это придется сделать с помощью метода Add коллекции Workbooks:

...Workbooks.Add

    Для завершения обсуждения проблем, связанных с объектами верхнего уровня Microsoft Excel, приведем несколько примеров.

Объект Application
oApp = CREATEOBJECT("EXCEL.APPLICATION")
oApp = GETOBJECT(" ","EXCEL.APPLICATION")

    Любая из этих строк приведет к запуску новой копии Excel в скрытом виде.

oApp = GETOBJECT(,"EXCEL.APPLICATION")

    Обеспечит ссылку на текущее приложение Excel. Если же Excel на компьютере не запущен, будет сгенерировано сообщение об ошибке.

Объект Sheet
oExSheet = CREATEOBJECT("EXCEL.SHEET")
FOR nVal = 1 TO 10
     oExlSheet.Cells(nVal, nVal).Value = nVal * nVal
ENDFOR
* Если хотите увидеть результат, уберите комментарий в следующий строке
* oExlSheet.Application.Visible = .T.
oExlSheet.SaveAs("TEMP.XLS")

    Создает новый рабочий лист в запускаемой невидимой копии Excel и заполняет его цифрами так, как это показано на рис. 10.4. Созданная таблица сохраняется в файле TEMP.XLS в папке, установленной по умолчанию для Excel.


Рис. 10.4.
oExlSheet = GETOBJECT("RAS_1.XLS", "EXCEL.SHEET")
oExlSheet.Range("G2").Value = 16 {dt>oExlSheet.Range("G3").Value = 10 {dt>oExlSheet.Parent.Save && Сохраняем рабочую книгу
? oExlSheet.Range("G4").Value

    Создает ссылку на первый рабочий лист в файле RAS_1.XLS. Файл в данном случае должен располагаться в папке, указанной по умолчанию для приложения, использующего OLE Automation, иначе необходимо указать путь к нему. В этот файл, содержащий результаты расчетов, мы заносим новые данные в ячейки G2 и G3, сохраняем данные, а затем выводим результат вычислений из ячейки G4, где записана формула, вычитающая G3 из G2.

Объект Chart
oExlChart = CREATEOBJECT("EXCEL.CHART")
* Стираем данные по умолчанию на рабочем листе со значениями
oExlChart.Parent.Sheets(2).Range("A1:D10").Clear
FOR nVal = 1 TO 10
     * Заполняем таблицу новыми значениями
     oExlChart.Parent.Sheets(2).Cells(nVal,1).Value = nVal {dt>     oExlChart.Parent.Sheets(2).Cells(nVal,2).Value = nVal * nVal
NEXT
* Строим график по новым значениям по колонкам
oExlChart.ChartWizard(oExlChart.Parent.Sheets(2).Range("A1:B10"),,,2)
* Смотрим, что получилось
oExlChart.Application.Visible = .T.
WAIT

    Создается новый рабочий лист с диаграммой. Сначала мы аполняем необходимыми данными второй рабочий лист, на котором размещаются данные. Затем с помощью метода ChartWizard обновляем диаграмму на первом рабочем листе. В методе ChartWizard из большого числа параметров мы устанавливаем только область данных и условие построения его по колонкам. Остальные параметры принимают значения по умолчанию. После этого выводим Excel на экран и используем команду WAIT для того, чтобы рабочая книга не была выгружена после завершения работы программы.

oExlChart = GETOBJECT("RAS_1.XLS", "EXCEL.CHART")
oExlChart.ChartTitle.Text = "Результаты продаж"

    Создает ссылку на первый рабочий лист с диаграммой в файле RAS_1.XLS. В файле должен быть предварительно создан объект Chart с помощью команды Chart в меню Insert.

Управление объектами Word for Windows

    При работе с объектами Word for Windows функция CREATEOBJECT() запускает новую копию приложения только в том случае, если на компьютере это приложение еще не работает. При этом функция GETOBJECT() не может использоваться для ссылки на документ. Если она используется в виде

oWrd = GETOBJECT(" ","WORD.BASIC")
    то ее применение аналогично функции CREATEOBJECT().
    Задание функции в виде

oWrd = GETOBJECT(,"WORD.BASIC")

    всегда приводит к ошибке.
    В отличие от Excel текстовый процессор Word for Windows имеет только один объект OLE Automation - WordBasic (в синтаксисе мы пишем Word.Basic). Это означает, что управлять документом Word из другого приложения мы можем только посредством выполнения команд WordBasic.
    Для того чтобы продемонстрировать пример создания объекта Word, решим классическую для любого начинающего программиста задачу - выведем на экран слово "Hello!" В связи с тем, что читатель одиннадцатой главы этой внушительной по объему книги вряд ли захочет относить себя к начинающим программистам, усложним задачу. Загрузим на компьютере Word и Access. Теперь, находясь в Access, напишем заветное слово в документе Word.
    Для решения этой задачи в контейнере БД Access перейдем на вкладку Модули. На панели инструментов нажмем кнопку Вставить процедуру. В появившемся диалоговом окне напишем ее название, например CallWord. В окне Модуль напишем следующий код:

Public Function CallWord() As Integer
     Dim oWbApp As Object
Set oWbApp = CreateObject("Word.Basic")
oWbApp.FileNew ` Открываем новый документ
oWbApp.Insert "Hello!" ` Вписываем в документ слово
     Set oWbApp = Nothing
     Exit Function
End Function

    Запустите этот модуль на выполнение. Напоминаем простейший способ сделать это - нажмите кнопку на панели инструментов Окно отладки и в появившемся окне наберите имя процедуры, после чего нажмите клавишу Enter. Смело переходите в Word и рассматривайте появившееся там слово.
    Если вас испугало многообразие объектов в Excel и вы уже обрадовались наличию в Word всего одного объекта, то, возможно, ваша радость преждевременна. При управлении документом Word с помощью OLE Automation есть одна существенная для программиста неприятность.
    Команды WordBasic используют поименованные аргументы, а посредством OLE Automation ссылаться на аргументы можно только по их положению. Например, вы хотите отключить вывод предупреждения при сохранении документа. В файле контекстной справки WordBasic вам будет подсказан следующий синтаксис команды ToolsOptionsSave

ToolsOptionsSave [.CreateBackup = number] [, .FastSaves = number] [, .SummaryPrompt = number]
    В макросе Word вы, соответственно, можете написать:
ToolsOptionsSave .SummaryPrompt = False

    Для того чтобы выполнить эту команду из OLE-контроллера, необходимо знать порядковый номер этого аргумента в команде:

oWbApp.ToolsOptionsSave , , 0

10.3. Использование OLE Automation для передачи данных

    В практике создания систем автоматизации обработки данных программисту очень часто приходится сталкиваться с задачей графического представления данных. В комплекте со всеми средствами разработки Microsoft поставляется специальная утилита Microsoft Graph 5.0, которая как нельзя лучше подходит для этих целей.
    В этом параграфе мы расскажем, как в пользовательском приложении можно использовать Microsoft Graph 5.0, а также остановимся на основных возможностях графического представления данных, которые предоставляет Microsoft Excel.
    С помощью Microsoft Graph 5.0 мы можем легко встроить в форму в виде OLE-объекта графики самого разнообразного вида, которые помогут пользователю лучше разобраться с тенденциями изменения интересующих его показателей. MS Graph 5.0 имеет интуитивно понятный интерфейс, разобраться с которым в крайнем случае поможет обширная справочная информация. Но если мы не хотим заставлять пользователя нашей прикладной программы изучать еще и англоязычный интерфейс MS Graph, нам придется позаботиться об управлении процессом графического представления данных из программы с помощью средств OLE Automation. В связи с актуальностью этого вопроса остановимся на нем возможно подробнее.
    На рис. 10.5 представлена иерархическая схема объектов MS Graph 5.0, а в табл. 10.3 - их краткое описание.

Таблица 10.3. Описание объектов MS Graph 5.0
ОбъектОписание
ApplicationСодержит установки в целом для приложения
AxisГоризонтальные или вертикальные оси графика
AxisTitleЗаголовок одной из осей графика
BorderРамка
ChartГрафик
ChartAreaОбласть графика, которая простирается и за внешние границы области, в которой вычерчивается график (поля, заголовки осей, описания данных и т. д.)
ChartGroupГруппа серий данных, представленных в виде одного графика. Простейший график содержит один объект ChartGroup
ChartTitleЗаголовок графика
DataLabelДополнительное описание для графика одной серии данных (может иметь отношение ко всей серии или к одной точке)
DownBarsПрямоугольник, который на линейном графике соединяет значение одной серии данных с более низким значением другой серии данных
DropLinesВертикальные линии, соединяющие точки графика со значениями на оси Y
ErrorBarsЛинии, графически отображающие ошибку расчета значения в графиках X-Y
FloorКоординатная поверхность, служащая основанием для трехмерного графика
FontШрифт
GridLinesЛинии координатной сетки
HiLoLinesВертикальные линии, которые соединяют максимальное и минимальное значения для различных серий данных
InteriorГрафическое оформление (фон, тень и т. д.)
LegendОписание серии данных для графика
LegendEntryНаименование серии данных, которое берется из колонки с данными и может быть изменено только на листе с данными
LegendKeyОбозначения для серии данных
PlotAreaОбласть непосредственного расположения графика
PointТочка в серии данных
SeriesСерия данных
SeriesLinesЛиния для обозначения серии данных
TickLabelsЗначения для засечек на оси графика
TrendLineЛиния тренда
UpBarsПрямоугольник, который на линейном графике соединяет значение одной серии данных с более высоким значением другой серии данных
WallsБоковые координатные поверхности для трехмерных графиков

    Перечисленные 27 объектов позволяют достаточно гибко программировать внешний вид графиков, предоставляя доступные для них свойства и методы, список которых приведен в табл. 10.4. Все объекты имеют свойства Application (возвращает имя приложения, создавшего объект), Creator (возвращает идентификатор приложения, создавшего объект - для Apple Macintosh) и Parent (возвращает имя родительского объекта), поэтому они не указаны в таблице.

Таблица 10.4. Свойства и методы объектов MS Graph 5.0
ОбъектСвойстваМетоды
ApplicationChartWizardDisplay, HasLink, Name, Visible, Chart, QuitSaveAsOldExcelFile-Format
AxisAxisBetweenCategories, AxisGroup, AxisTitle, Border, Crosses, CrossesAt, HasMajorGridlines, HasMinorGridlines, HasTitle, MajorGridlines, MajorTickMark, MajorUnit, MajorUnitIsAuto, MaximumScale, MaximumScaleIsAuto, MinimumScale, MinimumScaleIsAuto, MinorGridlines, MinorTickMark, MinorUnit, MinorUnitIsAuto, ReversePlotOrder, ScaleType, TickLabelPosition, TickLabels, TickLabelSpacing, TickMarkSpacing, TypeDelete
AxisTitleBorder, Caption, Font, HorizontalAlignment, Interior, Left, Name, Orientation, Shadow, Text, Top, VerticalAlignmentDelete
BorderColor, ColorIndex, LineStyle, Weight -
ChartArea3DGroup, AutoScaling, Bar3DGroup, ChartArea, ChartTitle, Column3DGroup, Corners, DepthPercent, DisplayBlanksAs, Elevation, Floor, GapDepth, HasAxis, HasLegend, HasTitle, HeightPercent, Legend, Line3DGroup, Perspective, Pie3DGroup, PlotArea, PlotVisibleOnly, RightAngleAxes, Rotation, SizeWithWindow, SubType, SurfaceGroup, Type, Walls, WallsAndGridlines2D, ApplyDataLabels, AreaGroups, AutoFormat, AxesBarGroups, ChartGroups, ChartWizard, ColumnGroups, Delete, DoughnutGroups, LineGroups, OmitBackground, PieGroups, RadarGroups, SeriesCollection, SetEchoOn, XYGroups
ChartAreaBorder, Font, Height, Interior, Left, Name, Shadow, Top, WidthClear, ClearContents, ClearFormats, Copy
Chart-GroupAxisGroup, DoughnutHoleSize, DownBars, DropLines, FirstSliceAngle, GapWidth, HasDropLines, HasHiLoLines, HasRadarAxisLabels, HasSeriesLines, HasUpDownBars, HiLoLines, Overlap, RadarAxisLabels, SeriesLines, SubType, Type, UpBars, VaryByCategoriesSeriesCollection
ChartTitleBorder, Caption, Font, HorizontalAlignment, Interior, Left, Name, Orientation, Shadow, Text, Top, VerticalAlignmentDelete
DataLabelAutoText, Border, Caption, Font, HorizontalAlignment, Interior, Left, Name, NumberFormat, Orientation, Shadow, ShowLegendKey, Text, Top, Type, VerticalAlignmentDelete
DownBarsBorder, Interior, NameDelete
DropLinesBorder, NameDelete
ErrorBarsBorder, EndStyle, Name, Clear FormatsDelete
FloorBorder, Interior, NameClear Formats
FontBackground, Bold, Color, ColorIndex, FontStyle, Italic, Name, OutlineFont, Shadow, Size, Strikethrough, Subscript, Superscript, Underline-
GridLinesBorder, NameDelete
HiLoLinesBorder, NameDelete
InteriorColor, ColorIndex, InvertIfNegative, Pattern, PatternColor, PatternColorIndex-
LegendBorder, Font, Height, Interior, Left, Name, Position, Shadow, Top, WidthClear, ClearContense, Copy, Delete, LegendEntries
Legend-EntryFont, Index, LegendKeyDelete
LegendKeyBorder, Interior, InvertIfNegative, MarkerBackgroundColor, MarkerBackgroundColorIndex, MarkerForegroundColor, MarkerForegroundColorIndex, MarkerStyle, SmoothClearFormats, Delete
PlotAreaBorder, Font, Height, Interior, Left, Name, Top, WidthClearFormats
PointBorder, DataLabel, Explosion, HasDataLabel, Interior, InvertIfNegative, MarkerBackgroundColor, MarkerBackgroundColorIndex, MarkerForegroundColor, MarkerForegroundColorIndex, MarkerStyle, PictureType, PictureUnitApplyDataLabels, ClearFormats, Copy, Delete
SeriesAxisGroup, Border, ErrorBars, Explosion, HasDataLabels, HasErrorBarsInterior, InvertIfNegative, MarkerBackgroundColor, MarkerBackgroundColorIndex, MarkerForegroundColor, MarkerForegroundColorIndex, MarkerStyle, PictureType, PictureUnit, Smooth, Type, ApplyDataLabels, ClearFormats, Copy, DataLabels, Delete, ErrorBar, Points, Trendlines
Series-LinesBorder, NameDelete
TickLabelsFont, Name, NumberFormat, OrientationDelete
TrendLineBackward, Border, DataLabel, DisplayEquation, DisplayRSquared, Forward, Index, Intercept, InterceptIsAuto, Name, NameIsAuto, Order, Period, TypeClear Formats, Delete
UpBarsBorder, Interior, NameDelete
WallsBorder, Interior, NameClearFormats

Построение графиков с помощью MS Graph 5.0

    Возможности отображения данных с помощью MS Graph 5.0 рассмотрим на примере построения формы в Visual FoxPro, в которой пользователь мог бы анализировать изменение данных с помощью графиков различного типа. Внешний вид такой формы приведен на рис. 10.6. Форма включает внедренный объект MS Graph 5.0 для отображения графика, раскрывающийся список для изменения отображаемых данных, раскрывающийся список и две кнопки выбора для изменения типа графика, кнопку управления для закрытия формы и элементы внешнего оформления.


Рис. 10.6.

    Для создания этой формы предварительно нам придется создать вспомогательную таблицу для хранения внедренного объекта MS Graph (графика). В этой же таблице (ее структура приведена в табл. 10.5) удобно хранить и дополнительную информацию о заголовках, а также сам запрос для получения наиболее "свежих" данных. Создать ее можно интерактивно с помощью Конструктора таблицы и информации, приведенной в табл. 10.5, или, что будет быстрее, с помощью следующих команд:

CREATE TABLE Graphs (title C(25), number I, query M, y_number I,;
     y1_caption C(25), y2_caption C(25), graph G)
APPEND BLANK
APPEND GENERAL graph CLASS "MSGraph"
Таблица 10.5. Структура таблицы GRAPHS.DBF для хранения внедренного графика
ПолеТипШиринаНазначение поля
TITLECharacter25 Заголовок графика
NUMBERInteger4Номер графика
QUERYMemo4Команда SQL запроса
Y_NUMBERInteger4Число осей Y
Y1_CAPTIONCharacter25Заголовок первой оси Y
Y2_CAPTIONCharacter25 Заголовок второй оси Y
GRAPHGeneral4График в виде внедренного объекта MS Graph 5.0

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

SELECT m.month_name,SUM(d.Price*d.quantity),m.month_numb
FROM Months m,Invoices i,Inv_Details d WHERE i.kod_id = d.kod_id AND
MONTH(i.inv_date) = m.month_numb GROUP BY m.month_name ORDER BY m.month_numb
INTO CURSOR Datafile

    Для временного хранения результата запроса мы используем курсор с именем Datafile.
    Теперь откроем Конструктор формы и разместим в новой форме объект OLE Bound Control. Присвоим ему имя olbGraph. В Data Environment формы добавим только что созданную таблицу и для свойства ControlSource объекта olbGraph выберем поле graph.
    В коде события Init обновим данные для отображаемого графика:

ThisForm.LockScreen = .T.
SELECT Graphs
GO TOP
cCom = Query
cCom =LEFT(cCom, LEN(cCom) - 2)
* Выполняем запрос, записанный в поле примечаний Query
&cCom
ThisForm.RefreshGraph
ThisForm.ChangeGraphType
ThisForm.LockScreen = .F.

    В коде для события Load формы опишем массив aType возможных типов графиков. В дальнейшем этот массив будет источником данных для списка типов графиков:

PUBLIC ARRAY aType[4,2]
aType[1,1] = "С областями"
aType[2,1] = "Гистограмма"
aType[3,1] = "График"
aType[4,1] = "Круговая"
aType[1,2] = 1
aType[2,2] = 3
aType[3,2] = 4
aType[4,2] = 5
    Тогда в событии Destroy формы не забудем стереть этот массив:
RELEASE aType
    Для отображения названий графиков создадим раскрывающийся список с именем cmbData. Присвоим ему следующие значения свойств:
RowSourceType = 2 - псевдоним;
RowSource = Graphs.title
    В коде события Init для объекта cmbData запишем:
This.Value = Graphs.Title{/dl>     В коде события InteractiveChange для объекта cmbData:
LOCAL cData, cCom
ThisForm.LockScreen = .T.
cData = This.Value
SELECT Graphs
LOCATE FOR Title = cData
cCom = Query
cCom =LEFT(cCom, LEN(cCom) - 2)
&cCom
ThisForm.RefreshGraph
ThisForm.ChangeGraphType
ThisForm.olbGraph.Object.ChartTitle.Caption = cData
ThisForm.LockScreen = .F.

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

  • RowSourceType = 5 - массив;
  • RowSource = aType - имя массива;
  • BoundColumn = 2 - значение свойства Value определяется по второй колонке массива.

    В коде события Init объекта cmbType для первоначального выбора первого типа графика запишем:

This.Value = 1{/dl>

    В коде события InteractiveChange для объекта cmbType предусмотрим выполнение пользовательского метода:

ThisForm.ChangeGraphType     Опишем для формы пользовательский метод ChangeGraphType:
LOCAL NType
nType = ThisForm.cmbType.Value
IF ThisForm.opgShow.Value = 1 {dt>     * Двухмерный график
     ThisForm.olbGraph.Type = NType
ELSE
     * Трехмерный график
     ThisForm.olbGraph.Type = NType + 8
ENDIF

    Для выбора двухмерного или трехмерного вида графика разместим в форме две кнопки выбора в группе кнопок выбора opgShow.
    В коде события InteractiveChange для объекта opgShow предусмотрим выполнение пользовательского метода:

ThisForm.ChangeGraphType
    Опишем для формы пользовательский метод RefreshGraph:
LOCAL cGraphString, nY_lim
cGraphString = ""
* Сколько полей должно участвовать в построении графика
nY_lim = Graphs.Y_number + 1
SELECT Datafile
* Создаем список полей, разделенных через табулятор,
* в конце строки записываем символ CHR(13)
FOR iCounter = 1 TO nY_lim
cGraphString = cGraphString + FIELDS(iCounter) ;
     + IIF(iCounter << nY_lim, CHR(9), CHR(13))
ENDFOR
* Приводим к символьному типу данные
* и формируем строку для передачи в OLE-объект
SCAN
     FOR iCounter = 1 TO nY_lim
cGraphString = cGraphString + IIF(TYPE(Fields(iCounter))='C',;
EVALUATE(FIELDS(iCounter));
,str(EVALUATE(FIELDS(iCounter))));
+ IIF(iCounter << nY_lim, CHR(9), CHR(13))
     ENDFOR
ENDSCAN
SELECT Graphs
APPEND GENERAL graph DATA cGraphString

Построение графиков с помощью MS Excel 7.0

    Работу с объектами Excel проиллюстрируем на примере создания формы для анализа данных в виде графиков, функционально аналогичной рассмотренной выше. При использовании Excel мы не связаны такими жесткими ограничениями на работу с данными, как в MS Graph, за счет того, что в Excel есть доступ к данным, на основании которых строится график через объект Sheet. В MS Graph данные располагаются в DataSheet, но к ним можно обеспечить только интерактивный, а не программный доступ. В то же время использование возможностей Excel требует больше ресурсов компьютера и лицензионной копии пакета на компьютере пользователя, в то время как MS Graph поставляется в составе всех пакетов разработки Microsoft. Посмотрите оба варианта форм для вывода графиков и выберите для себя более подходящий.
    Для воплощения нашей идеи в Конструкторе формы создадим следующие объекты.

  • oleChart - это объект OLE Container Control, с помощью которого мы встраиваем график Excel в форму. Нажимаем на панели инструментов Form Controls кнопку OLE Container Control и обводим в форме контур будущего графика. На экран выводится диалоговое окно Insert Object, в котором мы выбираем объект Excel Chart. Нажимаем кнопку OK и в обведенном контуре появляется график Excel, построенный на основании принятых по умолчанию данных, расположенных на втором рабочем листе таблицы. Одновременно, в соответствии с принципом редактирования на месте, изменяется главное меню Visual FoxPro для предоставления нам возможности отредактировать внешний вид представленного графика. Впоследствие можно вернуться к интерактивному редактированию графика, нажав на этом объекте правую кнопку мыши и выбрав в контекстном меню команду Edit.
  • cmdExit - кнопка управления для выхода из формы. Свойству Caption присвоим значение "OK".
  • cmdType - кнопка управления для изменения типа графика. При нажатии на кнопку будет происходить изменение типа графика. Свойству Caption присвоим значение "Тип".
  • cmdSubType - кнопка управления для изменения подтипа графика. При нажатии на кнопку будет происходить изменение подтипа графика. Свойству Caption присвоим значение "Подтип".
  • cmbData - комбинированный список для изменения данных для графика. Для этого объекта установим следующие значения свойств, отличных от принятых по умолчанию, после того как разместим элемент управления в форме:
BoundColumn = 2
ColumnCount = 2
ColumnWidths = 150,0
FirstElement = 1
Name = cmbData
NumberOfElements = ALEN(aDataTables)
RowSource = aDataTables
RowSourceType = 5
Style = 2
Value = "Total1"

    Как видно из перечисленных свойств, для формирования данных в списке мы будем использовать двумерный массив aDataTables. Первую колонку массива отведем для списка данных, доступных для графического отображения. Именно этот список будет видеть пользователь. Во второй колонке разместим названия источников данных (таблиц или курсоров). При запуске формы в списке будет выбран первый пункт, и для построения графика будет использована таблица Total1.
    Остальные элементы управления не являются обязательными и служат для улучшения внешнего вида формы.
    Для описания массива, используемого в комбинированном списке в событии Load объекта Form, запишем:

PUBLIC aDataTables(3,2)
aDataTables(1,1) = "Результаты продаж"
aDataTables(2,1) = "Доход"
aDataTables(3,1) = "Прибыль"
aDataTables(1,2) = "Total1"
aDataTables(2,2) = "Total2"
aDataTables(3,2) = "Total3"

    Этот массив можно описать в пользовательской программе и вне формы, и тогда набор данных, доступных для графического отображения, можно будет изменять. С этой целью в качестве источника данных для комбинированного списка можно использовать и таблицу с двумя полями, которую легче редактировать, чем массив.
    Для изменения данных на графике в соответствии с изменением выбранного пункта в списке в событии InteractiveChange объекта cmbData запишем следующий код:

ThisForm.LockScreen = .T.
SELECT (ThisForm.cmbData.Value)
&& Устанавливаем рабочую область
nRow = 2
SCAN && Считываем данные
ThisForm.oleChart.Object.Parent.Sheets("Sheet1").;
Cells(nRow,2).;
Value = Sum1 {dt> ThisForm.oleChart.Object.Parent.Sheets("Sheet1").;
Cells(nRow,3).;
Value = Sum2 {dt> ThisForm.oleChart.Object.Parent.Sheets("Sheet1").;
     Cells(nRow,4).;
Value = Sum3 {dt>     nRow = nRow + 1
ENDSCAN
ThisForm.LockScreen = .F.

    Здесь мы использовали блокировку изменения данных в форме, чтобы предотвратить последовательное изменение данных в каждом столбце графика (первая и последняя строка фрагмента кода). После ссылки на объект oleChart необходимо использовать свойство Object для того, чтобы Visual FoxPro понял, что указанное далее свойство Parent относится к объекту Excel. В противном случае Visual FoxPro решит, что мы ссылаемся на объект Form - родительский объект для объекта oleChart. Свойство Parent для объекта Excel нам необходимо для того, чтобы сослаться на объект Workbook. Только после этого мы можем использовать метод Sheets для получения ссылки на рабочий лист Sheet1, на котором находятся данные. Метод Cells позволяет нам указать конкретную ячейку таблицы, в которой мы хотим поменять данные с помощью свойства Value. Значения Sum1, Sum2 и Sum3 - это поля в таблицах, которые используются как источники данных для построения графиков и отображают изменение какого-то показателя во времени.
    Для отображения данных из первой таблицы при запуске формы в событии Init объекта Form следует поместить такой код:

ThisForm.cmbData.Value = ThisForm.cmbData.List(1,2) {dt>ThisForm.cmbData.InteractiveChange

    Добавим в форму собственные свойства NType и nSubType для задания типа и подтипа выводимого графика. Для этого достаточно в меню Form выбрать команду New Property. По умолчанию присвоим им значения 3 и 1 соответственно.
    В событии Click для объекта cmdType запишем следующий код:

IF ThisForm.nType >> 13
     ThisForm.nType = 0
ENDIF
ThisForm.nType = ThisForm.nType + 1
ThisForm.OleChart.Type = ThisForm.nType

    Это обеспечит приращение значения для типа графика при нажатии на кнопку "Тип" и сброс значения на начало отсчета при исчерпании числа типов графика.
    В событии Click для объекта cmdSubType запишем следующий код:

IF ThisForm.nSubType >> 3
     ThisForm.nSubType = 0
ENDIF
ThisForm.nSubType = ThisForm.nSubType + 1
ThisForm.OleChart.SubType = ThisForm.nSubType

    Для некоторых типов графиков в Excel существует меньшее число подтипов или их вообще не существует. В этом случае при нажатии на кнопку "Подтип" изменений в графике не произойдет. При необходимости можно учесть эти нюансы, слегка модернизировав приведенный выше фрагмент.
    В событии Click для объекта cmdExit для закрытия формы запишем следующий код:

RELEASE ThisForm

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


Рис. 10.7. Форма для представления графиков с помощью MS Excel 7.0

    В современных условиях все больше специалистов могут самостоятельно использовать стандартные пакеты программ. Например, готовить графики и другую расчетную информацию с помощью пакета Excel. В этом случае достаточно только правильно импортировать данные из СУБД в Excel. Один из возможных способов представлен ниже. Он реализован в форме "Характеристика модели автомобиля", разработка которой была описана в предыдущей главе.
    Программный код для передачи данных в Microsoft Excel:

oleExcel=CREATEOBJECT("Excel.Application")
&&Создаем объект Excel
oleExcel.Visible=.T. && Делаем его видимым
oleExcel.Workbooks.Add && Добавляем Книгу
oleExcel.Selection.ColumnWidth = 20 && Ширина 1 колонки
oleExcel.Range("B1").Select
oleExcel.Selection.ColumnWidth = 12 && Ширина 2 колонки
oleExcel.Range("C1").Select
oleExcel.Selection.ColumnWidth = 12 && Ширина 3 колонки
oleExcel.Columns("A:A").Select && Отмечаем 1 колонку
oleExcel.Selection.WrapText = .T.
&& Перенос непоместившихся символов на следующую строку
oleExcel.Range("A1:C1").Select
oleExcel.Selection.HorizontalAlignment =7
&& Заголовок размещаем в 1, 2 и 3 ячейках первой строки
oleExcel.Range("A2:C2").Select
oleExcel.Selection.HorizontalAlignment = -4108
&& Центрируем 1, 2 и 3 ячейки второй
&& строки
oleExcel.Columns("A:B").Select
oleExcel.Selection.Borders(2).Weight=2 && Линия справа
oleExcel.Columns("A:C").Select
oleExcel.Selection.Borders(3).Weight=2 && Нижняя линия
oleExcel.Range("A2:C2").Select
oleExcel.Selection.Borders(3).Weight=-4138
&& Верхняя линия
oleExcel.Selection.Borders(4).Weight=-4138
&& Нижняя линия
oleExcel.Range("A1:C1").Select
oleExcel.Selection.Font.Bold = .T.
oleExcel.Selection.Font.ColorIndex = 25
oleExcel.ActiveCell.FormulaR1C1 = "Характеристика модели автомобиля"
oleExcel.Range("A2").Select
oleExcel.ActiveCell.FormulaR1C1 = "Наименование модели"
oleExcel.Range("A2:C2").Select
oleExcel.Selection.Font.Bold = .T.
oleExcel.Range("B2").Select
oleExcel.ActiveCell.FormulaR1C1 = "Мощность"
oleExcel.Range("C2").Select
oleExcel.ActiveCell.FormulaR1C1 = "Крутящий момент"
******* Добавления значений *******
FOR I=1 TO KOL_Z
oleExcel.Cells(i+2,1).Value = all_value(i,1) {dt> oleExcel.Cells(i+2,2).Value = all_value(i,2) {dt> oleExcel.Cells(i+2,3).Value = all_value(i,3) {dt>ENDFOR
******* Строим диаграмму *******
oleExcel.ActiveSheet.ChartObjects.Add(245, 10, 340, 270).Select
oleExcel.ActiveChart.;
chartwizard(oleExcel.range(oleExcel.cells(2,1),oleExcel.cells(12,3)),;
-4100,5,1,1,1,2,"Десять лучших","","","")
&& Где:
&& Gallery - -4100,
&& Format - 5,
&& PlotBy - 1,
&& CategoryLabels - 1,
&& SeriesLabels - 1,
&& HasLegend - 2,
     && Title - "Десять лучших",
     && CategoryTitle - "",
     && ValueTitle - "",
     && ExtraTitle - ""
******* Изменяем угол просмотра *******
oleExcel.ActiveChart.Elevation = 0
oleExcel.ActiveChart.Rotation = 328

    Результат выполнения данного кода представлен на рис. 10.8.


Рис. 10.8.

Построение отчета в Word for Windows

    Чрезвычайно популярным пакетом для подготовки текстовой информации в нашей стране является текстовый процессор Word for Windows. Поэтому вполне объяснимо желание пользователя увидеть нужные ему данные в любимом редакторе и самостоятельно преобразовать их в требуемый вид. Приведем образец кода для передачи данных из формы "Характеристика модели автомобиля" в Microsoft Word:

oleWord=CREATEOBJECT("Word.Basic")
oleWord.FileNewDefault
oleWord.AppShow
oleWord.FilePageSetup(,,"2,54 см","2,54 см","2,5 см","1,5 см","0 см","21 см","29,7 см")
oleWord.FormatFont("14",0,9,0,0,0,0,1,0,"0 пт","0 пт",0,"", ,"Times New Roman Cyr", , 1)
oleWord.FormatParagraph( "0 см", "0 см","0 пт","0 пт", 0,"",1,1, 0, 0, 0, 0, 0,"0","0 см")
oleWord.Insert("Характеристика модели автомобиля")
oleWord.InsertPara
oleWord.InsertPara
*********Создание таблицы***************
oleWord.TableInsertTable( ,"3",ALLT(STR(Kol_z+1)))
oleWord.TableSelectColumn && Выделение колонки
oleWord.LeftPara && Выравнивание по левому краю
oleWord.TableSelectTable && Выделение таблицы
oleWord.TableRowHeight("0",2,"25 пт","0 см", 0,1)
oleWord.TableSelectColumn && Выделение колонки
oleWord.LineDown(1)
oleWord.LineUp(1)
oleWord.TableSelectColumn && Выделение колонки
oleWord.TableColumnWidth("11 см","0,38 см") && Установка ширины выделенной колонки
oleWord.NextCell
oleWord.NextCell
oleWord.TableSelectColumn && Выделение колонки
oleWord.TableColumnWidth("3,5 см","0,38 см")
oleWord.NextCell
oleWord.NextCell
oleWord.TableSelectColumn && Выделение колонки
oleWord.TableColumnWidth("3,5 см","0,38 см")
oleWord.TableSelectTable && Выделение таблицы
oleWord.FormatBordersAndShading (3, 0, 2, 2, 2, 2, 1, 1, 0, 0, 0, 0, 0, 0, "0 пт", 0, 0, 0,"0", -1)
oleWord.CharRight(1)
oleWord.LineUp(1)
oleWord.TableSelectRow && Выделение ряда
oleWord.TableHeadings
oleWord.Bold
oleWord.CenterPara
oleWord.FormatParagraph("","","","",4,"25 пт")
oleWord.CharLeft(1)
oleWord.Insert("Наименование модели")
oleWord.NextCell
oleWord.Insert("Мощность")
oleWord.NextCell
oleWord.Insert("Крутящий момент")
oleWord.NextCell
******* Добавления значений в таблицу*******
FOR I=1 TO KOL_Z
     oleWord.Insert(all_value(i,1))
     oleWord.NextCell
     oleWord.Insert(STR(all_value(i,2)))
     oleWord.NextCell
     oleWord.Insert(STR(all_value(i,3)))
     IF I<<KOL_Z
oleWord.NextCell
     ENDIF
ENDFOR

    Результат выполнения данного кода представлен на рис. 10.9.


Рис. 10.9. Пример передачи данных в Microsoft Word

Запись информации в Schedule+

    Используя возможности OLE Automation и наличие в составе пакета Microsoft Office специальной программы для планирования - Schedule+, мы можем расширить возможности нашего приложения за счет включения в него функций бизнес-планирования.
    Microsoft Schedule+ является средством бизнес-планирования, которое может использоваться в локальном режиме и в режиме совместного доступа. Программа Schedule+ является OLE-сервером, и поэтому мы можем использовать объекты этой программы для хранения, планирования и управления сведениями о встречах, собраниях, задачах, контактах и событиях. При планировании в расписание заносится оповещение, что позволяет не забыть о важной встрече, задаче или событии.
    Организация объектов в Schedule+ несколько отличается от Excel или MS Graph. Здесь имеются два типа объектов: таблица и пункт. Каждая таблица состоит из определенного количества строк, которые и представляются пунктами. Каждый пункт имеет определенный набор свойств. Описанная структура приведена на рис. 10.10.


Рис. 10.10. Структура объектов в Schedule+

    В качестве объектов типа таблица рассматриваются основные функциональные возможности Schedule+. Это запланированные события (Appointments), записи о лицах (Contacts), предупреждения (Alarms) и т. д. В свою очередь каждое событие, запись и т. п. является объектом типа пункт и имеет набор свойств. Например, для того чтобы записать сведения о новом лице в Visual Basic, необходимо выполнить такую программу:

Sub NewContact()

     Dim oSchedApp As Object, oSchedTable As Object, oSchedItem As Object
     * Запускаем скрытую копию Schedule+
     Set oSchedApp = CreateObject("SchedulePlus.Application")
     * Проводим процедуру регистрации
     If Not oSchedApp.LoggedOn Then
     oSchedApp.LogOn
     End If
     * Устанавливаем ссылку на объект типа таблица.
     * Свойство ScheduleLogged возвращает объект планирования для
     * зарегистрированного пользователя.
     Set oSchedTable = oSchedApp.ScheduleLogged.Contacs
     * Устанавливаем ссылку на объект типа пункт (новый пункт в таблице)
     Set oSchedItem = oSchedTable.New
     * Записываем в пункт данные с помощью его свойств
     oSchedItem.SetProperties FirstName:="Андрей", LastName:="Горев", _
     Notes:="Эффективная работа с СУБД на основе решений Microsoft", _
     PhoneBusiness:="(812)259-4277", PhoneFax:="(812) 112-6872"
    ` Стираем ссылки на объекты
Set oSchedItem = Nothing
Set oSchedTable = Nothing
Set oSchedApp = Nothing
End Sub

    После выполнения этой программы откройте Schedule+, и вы увидите, что на вкладке Contacts появилась новая запись.
    Совершенно аналогично можно записать в Schedule+ какое-либо планируемое событие. В этом случае дата и время начала и окончания планируемого события должны быть указаны обязательно.

Sub NewAppoint()
Dim oSchedApp As Object, oSchedTable As Object, oSchedItem As Object
Set oSchedApp = CreateObject("SchedulePlus.Application")
If Not oSchedApp.LoggedOn Then
     oSchedApp.LogOn
End If
' Устанавливаем ссылку на таблицу планируемых событий
Set oSchedTable = oSchedApp.ScheduleLogged.Appointments
' Создаем новое событие, в котором хотим участвовать
Set oSchedItem = oSchedTable.New
' Описываем это событие
oScedItem.SetProperties Text:="DevCon97", _
     Notes:="Ежегодная международная конференция разработчиков Microsoft", _
     Start:=("06/10/97 10:00"), _
     End:=("06/13/97 18:00")
' Стираем ссылки на объекты
Set oSchedItem = Nothing
Set oSchedTable = Nothing
Set oSchedApp = Nothing
End Sub

10.4. Применяем ActiveX

    В этом параграфе на примерах иерархического списка и календаря мы опишем, как можно использовать элементы ActiveX в пользовательском приложении.

Иерархический список

    Одним из поставляемых компонентов ActiveX (OCX) для средств разработки Microsoft является Outline. Необходимо сказать, что элемент управления Outline (файл MSOUTL32.OCX) представляет собой особую разновидность списка, в котором можно отображать элементы в иерархическом порядке. Этим пользуются при схематическом изображении каталогов и файлов в файловой системе. Именно такой метод применен в Windows 95 и Windows NT 4.0.
    У каждого элемента в списке Outline могут быть подчиненные элементы, которые визуально представляются дополнительными уровнями с отступами. Когда элемент развертывается, его подчиненные элементы становятся видимыми. Когда элемент сворачивается, его подчиненные элементы скрываются. Элементы в списке Outline могут также сопровождаться графикой, служащей визуальным обозначением состояния элемента.
    Элемент списка может сопровождаться любыми графическими элементами из числа следующих:

  • Линии древовидной структуры. Вертикальные и горизонтальные линии, связывающие первичные элементы с подчиненными. Линия дерева генерирует события Expand и Collapse.
  • Отступ. Характеристика уровня подчиненности элемента. Каждый уровень отступа соответствует определенному уровню подчиненности, который вы задаете с помощью свойства Indent.
  • Значок "плюс/минус". Указывает, видимы подчиненные элементы или скрыты. Если щелкнуть мышкой на значке "плюс", подчиненные элементы становятся видимыми и значок "плюс" заменяется значком "минус". Если щелкнуть мышкой на значке "минус", подчиненные элементы скрываются и значок минус заменяется значком "плюс".
  • Изображения типа. Отображают состояние элемента. На рисунках с изображением типа обычно показывается, допускает ли элемент, обладающий подчиненными элементами, развертывание или свертывание. Например, изображение закрытой папки указывает на то, что элементы каталога можно развернуть. Состояние элемента определяется пользователем. Рисунок с изображением типа генерирует события PictureClick и PictureDblClick.
  • Текст. Символьная строка, отображаемая для элемента.

    Каждый графический элемент может представлять собой область, которая способна реагировать на действия пользователя. Если щелкнуть на изображении элемента, активизируется специальная группа событий.
    Свойство Style позволяет задать или запретить отображение всех или некоторых графических элементов для каждого элемента списка Outline.
    Чтобы выбрать элемент списка, необходимо щелкнуть (или дважды щелкнуть) на строке с соответствующим текстом. Щелчка мышкой только на графическом элементе недостаточно.
    В качестве примера рассмотрим создание формы для Администратора БД, с помощью которой он может проконтролировать доступ пользователей к полям и таблицам БД. Для отображения структуры данных в БД Auto_Store используем элемент управления Outline.
    Итак, начнем с того, что в Visual FoxPro создадим новую форму. Затем, выбрав команду Options из меню Tools, активизируем вкладку Controls. На данной вкладке в списке Selected установим крестик на пункте Outline Control, как это показано на рис. 10.11. Далее нажмем кнопку View Classes панели инструментов Controls и в открывшемся меню выберем OLE Controls. На рис. 10.12 показано меню кнопки View Classes. Таким образом, у вас появится возможность визуально поместить данный элемент управления в форму посредством нажатия кнопки Outline Control (рис. 10.13). Однако в Visual FoxPro есть и более простой способ подключения элементов управления ActiveX, включающий в себя ледующие действия:


Рис. 10.11.

Рис. 10.12.

Рис. 10.13.
  1. Создаем новую форму.
  2. Нажимаем кнопку OLE Container Control панели инструментов Controls.
  3. Обводим мышкой контур на форме для элемента управления Outline Control.
  4. В открывшемся диалоговом окне Insert Object выбираем кнопку Insert Control и в списке Control Type дважды щелкаем по элементу Outline Control (рис. 10.14).

    Независимо от выбранного варианта действия в форме появится новый объект (рис. 10.15). Для определения свойств объекта Outline нажмите правую кнопку мыши на данном объектом и из контекстного меню выберите команду Properties.


Рис. 10.14. Диалоговое окно Insert Object для размещения объекта Outline Control

Рис. 10.15. Элемент управления Outline в разрабатываемой форме

    Для определения собственных изображений в иерархическом списке в диалоговом окне Properties активизируем вкладку Pictures, где для свойств PictureClosed и PictureOpen установим соответствующие графические файлы. Найти их на диске можно с помощью диалогового окна, вызываемого при нажатии кнопки Browse (рис. 10.16).


Рис. 10.16. Вкладка Pictures в диалоговом окне свойств Outline Control

    Для определения цвета фона (BackColor) и цвета текста (ForeColor) в диалоговом окне Properties активизируем вкладку Colors, где для свойства ForeColor определяем синий цвет (рис. 10.17).


Рис. 10.17.

    На рис. 10.18 показан Конструктор формы, использующий элемент управления Outline Control и заданные свойства ForeColor, PictureClosed и PictureOpen.


Рис. 10.18.

    Для события Init объекта Olec1 записываем следующий код:

&& Помещаем в массив aTabList список таблиц из словаря данных.
&& В связи с установленным уровнем доступа, равным по умолчанию пяти,
&& данный список таблиц фильтруем с помощью предложения WHERE
SELECT tableslist.table_name ;
FROM datavocabulary!tableslist ;
WHERE ALLT(Tableslist.table_name)<<>>"Sale" ;
AND ALLT(Tableslist.table_name)<<>>"Account" ;
AND ALLT(Tableslist.table_name)<<>>"Customer" ;
AND ALLT(Tableslist.table_name)<<>>"Order" ;
AND ALLT(Tableslist.table_name)<<>>"Salesman" ;
INTO ARRAY aTabList
&& Определяем значение переменной nnPabl
nnPabl=0
&& Последовательно заносим список полей для каждой таблицы
&& в массивы 1nnAr, 2nnAr, 3nnAr, <193>
&& После чего в объект Olec1 добавляем имена таблиц и соответствующих
&& этим таблицам полей, а для каждого поля устанавливаем отступ (indent)=2
&& и тип изображения (PictureType)=2
FOR X=1 TO ALEN(aTabList)
     ThisForm.Olec1.AddItem(ALLT(aTabList(X)))
     nnTab=ALLT(aTabList(X))
     nnAr="nnAr"+ALLT(STR(X))
     SELECT Tables.field_name ;
     FROM datavocabulary!tables ;
     WHERE Tables.table_name = nnTab ;
     INTO ARRAY &nnAr
     nnAddItem="ThisForm.Olec1.AddItem"
     nnArn="nnAr"+ALLT(STR(X))
     FOR I=1 TO ALEN(&nnArn)
&nnAddItem(ALLT(&nnArn(i)))
nnBeby=nnPabl+X+I-1
ThisForm.Olec1.indent(nnBeby)=2
ThisForm.Olec1.PictureType(nnBeby)=2
     ENDFOR
     nnPabl=nnPabl+ALEN(&nnArn)
ENDFOR

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


Рис. 10.19. Форма с иерархическим списком в действии

Календарь

    В следующем примере рассмотрим использование календаря для ввода или редактирования данных в поле, содержащем дату. Вместо набора даты вручную пользователь должен иметь возможность визуального выбора в календаре требуемой даты. После выбора дата должна автоматически записаться в нужное поле, как это показано на рис. 10.20. Для этого в Visual Basic откроем новый проект и создадим несложную форму. Чтобы сделать процесс создания формы максимально простым, используем, пожалуй, единственный визуальный инструмент разработчика, присутствующий в Visual Basic, - Data Form Designer - Конструктор формы для работы с данными, показанный на рис. 10.22. Необходимые пояснения для построения формы вы найдете на этом же рисунке. Построенная Конструктором форма приведена на рис. 10.21. Как видите, она мало пригодна для использования в пользовательском приложении, хотя черновая работа по размещению полей и выбора для них элементов управления выполняется автоматически без нашего участия. Мы привнесли в форму минимальные изменения и за счет корректировки значений свойств привели ее к виду, показанному на рис. 10.20. Потребовалось выполнить для объектов Label и CommandButton изменения значений свойства Caption, перемещение и изменение размеров некоторых элементов управления. Если у вас возникнут трудности с изменением размера элемента управления Data Control, установите значение свойства Allign равным 0.


Рис. 10.20. Изменение даты с помощью календаря

Рис. 10.21.

Рис. 10.22.

    Для вызова календаря разместим рядом с полем для отображения даты еще одну кнопку. Дадим ей имя cmdCallData и заголовок "Новая дата". Щелкнем на кнопке два раза и в появившемся окне для записи кода в процедуре cmdCallData_Click() запишем строчку:

frmNewDate.Show

    Тем самым мы обеспечиваем вызов формы с календарем.
    Для создания вспомогательной формы с календарем в меню Insert выберем команду Form. Дадим ей имя frmNewDate и заголовок "Выберите дату". На панели инструментов нажмем кнопку Calendar и, удерживая левую кнопку мыши, обведем на форме соответствующий контур. Появившемуся на форме объекту дадим имя olcCalendar. В Visual Basic свойства для объекта ActiveX можно изменять и в его собственном окне свойств, вызываемом из контекстного меню, и в окне Properties Visual Basic. Изменить значение даты, записанное в поле первой формы, можно с помощью следующей процедуры:

Private Sub olcCalendar_AfterUpdate()
     frmAccounts.txtFields(1) = olcCalendar.Value
End Sub

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

Глава 9 || Содержание || Глава 11