Домашняя страница Undo Do Save Карта сайта Обратная связь Поиск по форуму
МИР MS EXCEL - Гость.xls

Вход

Регистрация

Напомнить пароль

 

= Мир MS Excel/Статьи об Excel

МЕНЮ САЙТА
  • 1
  • 2
  • 3

КАТЕГОРИИ РАЗДЕЛА
Циклы [4]
Циклы VBA
Операторы ветвления [2]
Модули классов [2]
Создание, поля, свойства, события, когда использовать
Работа с приложениями и библиотеками [2]
Создание надстроек для ексель на .net, вызов компонентов .net
Прикладное программирование [5]
Примеры разработки прикладных программ на VBA

ОПРОСЫ
Какой версией Excel Вы пользуетесь?
Всего ответов: 57579
Главная » Статьи » Программирование на VBA » Работа с приложениями и библиотеками

AUTOMATION: использование Раннего и Позднего Связывания

Перевод статьи «Using early binding and late binding in Automation» с официального сайта поддержки Майкрософт. Перевод выполнен Романом Вороновым от 14-го июля 2015.

КРАТКОЕ СОДЕРЖАНИЕ

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

ДОПОЛНИТЕЛЬНАЯ ИНФОРМАЦИЯ

Automation – это процесс, при котором некоторый программный компонент взаимодействует и / или контролирует другой программный компонент посредством Компонентно-Объектной Модели (на англ. COM) Майкрософта. Этот принцип лежит в основе большинства кросс-компонентных взаимодействий в таких языках как Visual Basic (VB) или Visual Basic for Applications (VBA) и стал неотъемлемой частью большинства программ.

Исторически, объект Automation – это любой объект, поддерживающий интерфейс IDispatch. Этот интерфейс позволяет клиенту запрашивать методы и свойства во время исполнения программы. Происходит это даже без предварительного знания об объекте на стадии разработки, с которым будет взаимодействие. Это называется поздним связыванием. Сегодня, однако, термин «Объект Automation» может быть использован в отношении любого объекта COM, даже не поддерживающего интерфейс IDispatch (и, следовательно, недоступного для позднего связывания). В этой статье предполагается, что объект, который Вы автоматизируете, поддерживает как позднее, так и раннее связывание.

Что же такое связывание?

Связывание – это процесс сопоставления вызова функции, написанной программистом, с конкретным кодом (внутренним или внешним), который эту функцию реализует. Это происходит при компилировании, когда все используемые в коде функции должны быть привязаны до того, как код будет исполнен.

Для большего понимания рассмотрим «связывание» применительно к публикации некоторых материалов. Представьте, что Ваш код – это текст книги, где в каком-то параграфе Вы пишите: «подробности смотрите далее в главе 12, на странице Х». Вы не знаете точный номер страницы, пока книга не закончена. Поэтому до того, как параграф будет прочтён, все страницы книги должны быть «связаны» вместе чтобы Вы могли проставить конкретный номер страницы для ссылки. Приходится ждать, пока книга будет закончена, «связана», чтобы можно было обращаться к разным её частям.

Связывание в программировании носит те же черты. Ваш код состоит из частей, которые должны быть собраны вместе до того, как код может быть «прочтён». Связывание – это замена имён функций на адреса в памяти (или, что точнее, на смещения памяти), куда код будет «прыгать» при вызове этих функций. Для COM объектов адрес – это смещение по памяти в таблице указателей объекта (так называемая v-таблица). COM-функция связывается через таблицу указателей.

Структура COM-объекта довольно проста. Когда код содержит ссылку на объект – он содержит косвенное указание на вершину таблицы указателей. А таблица указателей - ни что иное как массив адресов в памяти, каждая запись которого ведёт к разным функциям данного объекта. Например, для вызова 3-й функции COM-объекта нужно прыгнуть сверху таблицы до 3-й записи и пройти к указанной здесь области памяти. Это исполнит код функции и, по завершению, возвратит нас к исполнению следующей строки основного кода.

Все COM объекты наследуются от интерфейса IUnknown («неизвестный» интерфейс, англ.) и первые три записи в таблице указателей являются методами этого интерфейса. Поэтому, например, при необходимости освободить объект – вызывается третья функция в таблице указателей (IUnknown::Release).

К слову, эта работа выполняется языком Visual Basic самостоятельно, «за кулисами» программирования. Как VB программист, Вам не придётся работать с таблицей указателей напрямую. Однако, это - основа связывания COM-объектов, крайне важная для понимания процесса связывания.

Раннее связывание

Описанный выше пример – классическое раннее связывание (или связывание через таблицу указателей). Для всех COM объектов эта форма связывания имеет место всякий раз, когда вызывается IUnknown интерфейс этого объекта. Но что насчёт других функций этого объекта? Как вызвать метод обновления или родительское свойство? Эти привычные функции уникальны для объекта. А если положение этих функций в таблице указателей заведомо неизвестно, то как найти адреса для их вызова?

Ответ, конечно, зависит от того, знаем ли мы (или нет) заведомо об устройстве таблицы указателей объекта. Если мы знаем, то можно проделать тот же трюк, что ранее описан про освобождение объекта через метод интерфейса IUnknown: «прыжком» заданной длины до нужного места в таблице указателей. Это пример того, что принято считать «ранним связыванием».

Для применения раннего связывания к объекту следует ориентироваться в его таблице указателей. На языке Visual Basic это можно сделать через добавление ссылки на библиотеку типов, описывающую объект, его интерфейс (таблица указателей) и на все функции объекта. После чего можно объявить объект принадлежащим к конкретному типу и использовать объект через его таблицу указателей. Например, если необходимо автоматизировать MSO Excel с использованием раннего связывания – следует добавить ссылку на «Microsoft Excel [?].0 Object Library» (где [?] зависит от версии используемого приложения Excel) в меню «References» (ссылки) проекта и объявить переменную с типом «Excel.Application». С этого момента любой вызов Вашей объектной переменной будет работать с ранним связыванием:

 

' Задать ссылку на 'Microsoft Excel 8.0 Object Library' в
' Project|References меню (или Tools|References для VB4 или VBA).

' Объявить объект через раннее связывание
 Dim oExcel As Excel.Application
 Set oExcel = CreateObject("Excel.Application")

' Свойство видимости вызывается через таблицу указателей
 oExcel.Visible = True


Этот приём отлично работает в большинстве случаев. Но что, если на стадии разработки нам заведомо неизвестно, какой объект мы будем использовать? К примеру, что, если необходимо обращаться к множеству версий Excel или к вообще неизвестному объекту?

Позднее связывание

COM включает интерфейс IDispatch. Объекты, использующие IDispatch, имеют либо диспинтерфейс (если IDispatch – единственный поддерживаемый ими интерфейс), либо двойной интерфейс (если плюс к первому у них есть привычный интерфейс, к которому можно применить раннее связывание). При использовании IDispatch интерфейса для связывания считается, что применяется «позднее связывание». При этом точные положения свойств и методов, вызываемых клиентом, в ходе работы программы определяются методами самого IDispatch. Возвращаясь к примеру с книгой: представьте, что вместо указания нужной страницы в тексте есть сноска, пройдя по которой мы найдём содержание, в котором ещё нужно будет найти номер нужной страницы. И всё это во время чтения нашей условной книги.

Магия интерфейса поддерживается двумя функциями: GetIDsOfName («получить идентификаторы имён» с англ.) и Invoke («вызов» с англ.). Первая функция связывает имена функций с особым идентификатором. А когда идентификатор нужной функции известен – оную можно вызвать с помощью функции Invoke. Такая форма вызова методов называется «поздним связыванием».

Запомните, в Visual Basic способ связывания задаётся объявлением объекта. Когда объект инициализируется как переменная типа «Object» - мы, по сути, говорим Visual Basic’у использовать интерфейс IDispatch, тем самым применяя позднее связывание:

 

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

' Объявляем объект для позднего связывания
 Dim oExcel As Object
 Set oExcel = CreateObject("Excel.Application")

' Свойство видимости определяется через интерфейс IDispatch
 oExcel.Visible = True


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

Заметьте, что «позднее связывание» касается вызываемой функции, а не способа её вызова. Из ранее изложенного материала следует, что к интерфейсу IDispatch уже применяется «раннее связывание». Для задания свойства видимости, Visual Basic обращается к таблице указателей (IDispatch::Invoke). И уже COM-объект несёт ответственность за перенаправление запроса к корректной функции для отрисовки Excel приложения. Подобное перенаправление позволяет Visual Basic клиенту быть скомпилированным (при этом, привязанным к корректному адресу функции) и вместе с этим не знать саму функцию, с которой будет дальше работать.

Связывание идентификатора

Некоторые клиенты автоматизации (в первую очередь пакеты MFC и Visual Basic 3.0, хотя также касается Visual Basic 5.0, 6.0) используют смешанную форму позднего связывания – связывание идентификатора. Если COM объект известен на этапе разработки, идентификаторы вызываемых функций могут быть захвачены и направлены на IDispatch::Invoke напрямую. При этом нет необходимости в вызове GetIDsOfNames во время работы программы. Этим значительно увеличивается производительность, так как вместо двух вызовов COM на каждую функцию - происходит только один.

Связывание идентификатора нельзя выбрать напрямую в Visual Basic 5.0 или 6.0. Оно используется для объектов, которые обозначены в библиотеке типов, но не содержат обычного интерфейса (объекты только с одним диспинтерфейсом) и для элементов управления ActiveX. При этом везде, где это возможно, Visual Basic будет использовать раннее связывание по умолчанию.

Какое связывание стоит использовать?

Ответ на этот вопрос зависит в первую очередь от структуры Вашего проекта. Microsoft рекомендует раннее связывание в большинстве случаев. Однако, могут быть причины выбрать и позднее связывание. Раннее связывание – предпочтительный метод. Его достоинство – в привязке приложения напрямую к адресу вызываемой функции, никаких поисков ссылок в режиме исполнения программы. С точки зрения скорости исполнения – минимум вдвое быстрее позднего связывания.

Раннее связывание также обеспечивает безопасность при работе с типами. Когда у Вас привязана ссылка к библиотеке типов компонента, Visual Basic поддерживает IntelliSense технологию (автоматическое предложение свойств и методов по первым введённым символам), что позволяет кодировать каждую функцию корректно. Visual Basic также предупредит, если тип данных параметра или возвращаемого значения некорректен, что сэкономит время на написании и исправлении кода.

Позднее связывание по-прежнему применимо в ситуациях, когда конкретный интерфейс объекта ещё не известен на стадии разработки. Если предполагается, что Ваше приложение будет обращаться к множеству неизвестных серверов или ему потребуется вызывать функции по имени (например, с помощью CallByName функции в Visual Basic 6.0), тогда потребуется позднее связывание. Позднее связывание также полезно при работе с вопросами совместимости между разными версиями компонента, интерфейс которого от версии к версии претерпевал изменения.

Преимущества раннего связывания призывают использовать оное везде, где это возможно.

Сохранение совместимости между версиями

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

Приложения Microsoft Office – хороший пример подобных COM-серверов. Офисные приложения обычно расширяют свои интерфейсы для добавления нового функционала или для коррекции предыдущих меж-версионных наработок. Если требуется автоматизировать офисное приложение, раннее связывание рекомендуется с самой ранней версией продукта из предполагаемых в системе Вашего клиента. Например, если нужно разработать решение для Excel 95, Excel 97, Excel 2000 и Excel 2002 – следует использовать библиотеку типов для Excel 95 (XL5en32.olb) для обеспечения совместимости со всеми тремя версиями.

Офисные приложения показывают, как объектные модели с большими двойными интерфейсами могут испытывать серьёзные ограничения при переносе на некоторые платформы. Наилучшим будет выбрать IDispatch интерфейс для работы на разных платформах. Более подробно о поддержке совместимости с офисными приложениями можно посмотреть ЗДЕСЬ (ссылка на англоязычную статью).

ССЫЛКИ

Более детальную информацию по COM, таблицам указателей и использованию автоматизации можно найти в книгах:
1). Rogerson, Dale, Inside COM, MSPRESS, ISBN: 1-57231-349-8.
2). Curland, Matt, Advanced Visual Basic 6, DevelopMentor, 0201707128.

О СТАТЬЕ

Идентификатор статьи: 245115, последнее обновление от 5 ноября 2007 года в 16:31:03, версия 7.2
Применимо к:
- Microsoft Office Ultimate 2007
- MicrosoftOffice Enterprise 2007
- MicrosoftOffice Professional 2007
- MicrosoftOffice Professional Plus 2007
- MicrosoftOffice Standard 2007
- MicrosoftOffice Home and Student 2007
- MicrosoftOffice Basic 2007
- MicrosoftOffice 2003, All Editions
- MicrosoftOffice XP Developer Edition
- MicrosoftOffice 2000 Developer Edition
- MicrosoftVisual Basic 5.0 Professional Edition
- MicrosoftVisual Basic 6.0 Professional Edition
- MicrosoftVisual Basic 5.0 Enterprise Edition
- MicrosoftVisual Basic Enterprise Edition for Windows 6.0
Ключевые слова: kbautomation kbinfo KB245115

Категория: Работа с приложениями и библиотеками | Добавил: Rioran (14.07.2015)
Просмотров: 6393 | Рейтинг: 5.0/1


Всего комментариев: 0
Добавлять комментарии могут только зарегистрированные пользователи.
[ Регистрация | Вход ]
Яндекс.Метрика Яндекс цитирования
© 2010-2024 · Дизайн: MichaelCH · Хостинг от uCoz · При использовании материалов сайта, ссылка на www.excelworld.ru обязательна!