Програмне взаємодія проектів Office 2000, MS Office, Програмні керівництва, статті

Зміст



Незважаючи на те що в назві статті вказано Office 2000, ми будемо розглядати питання взаємодії на прикладі Word 2000. Для інших додатків пакета принципи такої роботи cхожі, хоча і є деякі відмінності. Проте практично все, про що ми тут будемо розповідати, справедливо і для Office 97, і для Word 97 (наявні відмінності ми постараємося виділити).


Підкреслю також відразу, що вся робота буде виконуватися в середовищі редактора VBA, зокрема саме там буде виконуватися запуск макрокоманд на виконання.


Як зв’язати два документи Word


Постановка завдання виглядає наступним чином. Створіть документ Word з ім’ям DocSub.doc. Тепер в середовищі VBA включите в його програмний проект модуль коду (SubModule) і створіть в ньому дві прості процедури:

Sub DocSubProc1 ()
Msgbox “Працює процедура DocSubProc1”
End Sub
Sub DocSubProc2 (d%)
Msgbox “Працює процедура DocSubProc2”
          d = d + 1
End Sub

Зверніть увагу, що перша процедура автоматично потрапила в список макрокоманд проекту. У зв’язку з цим підкреслимо: макрокомандою є процедура, яка задовольняє таким умовам:



Тепер закриємо DocSub і створимо ще один документ з назвою DocMain, включимо в нього модуль коду MainModule, в якому напишемо макрокоманду

Sub DocMainMacro()
End Sub

Спробуємо відповісти на питання: яким чином можна з макрокоманди DocMainMacro звернутися до процедур DocSubProc1 і DocSubProc1 іншого документа? Питання безумовно важливий, тому що при досить серйозною розробці часто потрібно створити додаток у вигляді деякої системи взаємопов’язаних документів та їх програмних проектів.


Тривіальне вирішення проблеми – написати Call DocSubProc1 – не допоможе, тому що в цьому випадку ми отримаємо повідомлення про те, що такої процедури немає.


Принципи звернення до процедур проекту


Відкладемо на час рішення поставленого питання і розберемося спочатку з деякими базовими речами. В першу чергу відзначимо, що в загальному випадку звернення до процедури має вигляд:

Call [ProjectName.][ ModuleName.]ProcedureName

Тобто для точної ідентифікації процедури потрібно (але не обов’язково) додатково вказувати імена проекту і модуля, де вона міститься.


Важливе зауваження. Зверніть увагу, що в даному випадку використовується параметр ProjectName – ім’я проекту, що зовсім не одне і те ж, що ім’я документа. Ім’я документа є звичайним ім’ям файлу, причому в загальному випадку для однозначної його ідентифікації – із зазначенням повного шляху до нього. Ім’я проекту – це спеціальний внутрішній ідентифікатор, за допомогою якого здійснюється взаємодія програмної частини документів і шаблонів. За замовчуванням при створенні нового документа його проектом присвоюється стандартне ім’я – Project. Так що два створених нами документа мають однакові імена проектів, що ніяк не впливає на роботу, якщо документи використовуються в автономному режимі. Але у випадку програмного взаємодії часто необхідно, щоб імена проектів були різними. Імена встановлюються у вікні Properties для єдиного властивості проекту Name. Враховуючи це, змінимо імена проектів для наших документів на ProjMain і ProjSub (ми використовуємо різні ідентифікатори для проекту і документа, щоб розрізняти ці поняття). Відзначимо також, що шаблон Normal.dot має фіксоване ім’я файлу та проекту, тому у вікні Project він позначений одним ідентифікатором – Normal.


У яких випадках необхідно використовувати розширений варіант звернення до процедур? Для відповіді на це питання розглянемо невеликий приклад. Включіть в документ DocMain ще один новий модуль коду (Module1) і створіть в ньому процедуру:

Public Sub TestProc()
MsgBox “Працює DocMain.Module1.TestProc”
End Sub

Тепер зробіть в DocMainMaсro звернення до цієї процедури Call TestProc і запустіть макрокоманду – все спрацює нормально. Включіть в цей документ ще один модуль (Module2) з такою ж процедурою (тільки поміняйте видається повідомлення, щоб розрізнити роботу процедур). Запустіть на виконання DocMainMacro, і ви отримаєте повідомлення про помилку: двозначність імені процедури. В цьому випадку для звернення до потрібної підпрограмі потрібно змінити формат звернення, вказавши ім’я модуля:

Call Module1.TestProc

Зрозуміло, при роботі всередині одного проекту його ім’я вказувати не потрібно. Зверніть увагу, що при використанні дублікатних імен процедур в списку макрокоманд відбудуться відповідні зміни – вони будуть позначатися повними іменами.


Порада: Слідкуйте за появою підказок! Після введення імені модуля редактор видає підказку з переліком доступних процедур. Відсутність такої підказки говорить про те, що ви ввели невірне ім’я модуля (або відповідно недоступного проекту). Спробуйте звернутися до процедури іншого проекту наступним чином:

Call ProjSub.SubModule.DocSubProc1

Ще при введенні цього коду ви побачите, що проект ProjSub є недоступним (не з’явиться підказка). При запуску дії DocMainMacro з’явиться повідомлення про не знайденому ідентифікаторі.


Ще один варіант контролю введення доступних імен змінних і об’єктів виглядає так. Зазвичай принцип використання смислових імен змінних увазі використання в ідентифікаторі малих і великих букв. Так от, при введенні програмного коду використовуйте тільки нижній регістр (Малі літери) – тоді при завершенні введення оператора редактор VBA автоматично перетворює ім’я в вид, зазначений в описі змінної або об’єкта.


Звернення до процедур шаблону Normal


Тепер спробуємо попрацювати з процедурами шаблону Normal.


Увага! Я не рекомендую без особливої ​​потреби вносити зміни в шаблон Normal. Для налаштувань краще створити окремий шаблон, який може автоматично завантажуватися при запуску Word як глобального, якщо його записати в каталог C: WindowsAppication DataMicrosoftWordStartUp або в каталог … Office2000StartUp.


При експериментах з Normal.dot (чим ми зараз і займемося) краще зробити його вихідну копію і при завершенні досліджень відновити її. Більше того, мати копію Normal завжди корисно …


Включіть в Normal модуль Module1 з такою процедурою:

Sub NormalProc()
MsgBox “Працює Normal.Module.NormalProc”
End Sub

До неї можна звернутися з макрокоманди DocMainMacro за допомогою будь-якого з перерахованих нижче варіантів

Call Normal.Module1.NormalProc
Call Normal.NormalProc
Call NormalProc

З цього можна зробити кілька проміжних висновків:



Важливе зауваження. Саме звернення до процедури зовнішнього проекту можна зробити тільки тому, що ProjMain має посилання на нього у вигляді Normal: подивіться розділ References в описі проекту у вікні Project – вона була встановлена при створенні документа, так як приєднаним шаблоном був вказаний Normal. Назва ж проекту можна опустити в обігу, так як ім’я NormalProc є унікальним для обох проектів.


Створіть у Normal і в ProjSub дві процедури з однаковими іменами CommonProc. Тоді для звернення до процедури Normal з макрокоманди DocSubMacro потрібно обов’язково вказати ім’я проекту:

Call Normal.CommonProc ‘звернення з ProjSub до Normal

А для звернення до процедури свого ж проекту достатньо записати лише її ім’я:

Call CommonProc ‘звернення всередині проекту ProjSub


Ще один цікавий момент. При запису Call Normal з’явиться підказка з переліком припустимих елементів даного звернення. Тут потрібно звернути увагу на два моменти:



  1. Доступними компонентами проекту є тільки модулі коду і ThisDocument. Класи і форми (точніше, їх процедури) є недоступними для зовнішніх проектів.
  2. У списку компонентів видно імена процедур, але тільки (!) – Для унікальних ідентифікаторів. Якби ми створили в Normal ще один модуль і записали в нього процедуру NormalProc, то ім’я NormalProc зникло б зі списку «другого поля», але при цьому з’явилася б рядок Module2. Зрозуміло, що опускати ім’я модуля можна тільки для тих процедур, які з’являються в списку.

Звернення до процедур інших шаблонів


Нам поки не дуже зрозуміло, як можна пов’язати два документи Word, проте всі ми знаємо, що цей текстовий процесор надає два варіанти зв’язку документів і шаблонів. Напевно це може якось допомогти нам в організації їх програмного взаємодії. Тому зараз ми запишемо на диск створений раніше документ DocSub.doc, а також збережемо його ж у форматі шаблону з ім’ям DocSub.dot і потім закриємо цей шаблон. Тепер у нас в середовищі Word знаходиться тільки один документ DocMain, і ми спробуємо підключити до нього програмні компоненти шаблону DocSub.dot.


Варіант 1. Підключення глобального шаблону


За допомогою діалогового вікна Templates and Add-ins підключимо DocSub.dot до документа DocMain.doc у вигляді глобального шаблону. Потім перейдемо в середу VBA (нагадаємо, що код глобальних шаблонів не доступний для перегляду та редагування).


Всі спроби звернутися з макрокоманди DocMainMacro безпосередньо до процедури DocSubProc1 знову завершаться невдачею – код проекту глобального шаблону є недоступним для документа. Але те, що не можна зробити шляхом прямого звернення до процедури за допомогою оператора Call, можна виконати з використанням методу Run:


Application.Run “DocSub.SubModule.DocSubProc1”


Детальніше про використання методу Run читайте у цій статті нижче, а поки закрийте цей глобальний шаблон.


Варіант 2. Підключення приєднаного шаблона


За допомогою того ж вікна Templates and Add-ins підключіть DocSub.dot у вигляді приєднаного шаблона. Тепер буде працювати будь-який варіант звернення до DocSubProc1 з макрокоманди DocMainMacro:

Call ProjSub.SubModule.DocSubProc1
Call ProjSub.DocSubProc1
Call DocSubProc1


При цьому ви можете з подивом виявити, що всі процедури шаблону Normal стали недоступними для нашого проекту ProjMain – посилання на Normal замінила посилання на DocSub.dot.


Використання Object Browser


Однак всі наші дослідження по «доступності / недоступності» програмних проектів були б набагато ефективніше, якби ми відразу використовували команду View / Object Browser (F2).


Відкрийте документ DocMain.doc з приєднаним шаблоном DocSub.dot, виділіть в середовищі VBA в якості активного проекту ProjMain і натисніть F2. Розкрийте у вікні Object Browser список Project / Library – тут наведено перелік всіх проектів і бібліотек, доступних в даний момент активному проекту ProjMain. Нижче у вікні Classes наведено список компонентів виділеного проекту, а у вікні Members – процедур.


Тут потрібно мати на увазі, що, хоча, наприклад, для проекту ProjSub будуть показані включені до нього модулі форм і класів (якщо б ми їх вставили), вони будуть недоступні для програмного звернення для ProjMain.


Звернемо увагу ще на один цікавий момент. Для його ілюстрації прямо в середовищі VBA змініть для шаблону DocSub.dot ім’я проекту з ProjSub на ProjMain (тобто встановіть для двох проектів однакові імена), знову відкрийте вікно Object Browser і порівняйте це зображення з рис. 7. Видно, що в списку замість двох проектів ProjSub і ProjMain залишився тільки останній, причому він відноситься до шаблону DocSub.dot (див. склад модулів у вікні Classes). А документ DocMain.doc взагалі не представлений в Object Browser. Однак якщо ви почнете вводити в макрокоманді DocMainMacro код Call ProjMain, то по з’явилася підказкою легко здогадаєтеся, що в даному випадку під ProjMain мається на увазі як раз документ DocMain.


З цього можна зробити два висновки. Перший – при підключенні однойменного проекту будуть доступні його процедури тільки з унікальними іменами (для однойменних процедур потрібно обов’язково вказати назву проекту). Другий – краще, щоб всі проекти мали свої унікальні імена – у вас буде більше можливостей і менше головного болю.


Використання вікна References – рішення вихідної завдання


За розмовами «навкруги» ми впритул підійшли до проблеми, позначеної в першому пункті статті, – як зв’язати два документи Word. Переглянувши складу доступних програмних компонентів у вікні Object Browser, згадаємо, що для їх підключення в середовищі VB використовується команда References (меню Tools).


Давайте відкриємо це вікно – в ньому ми побачимо посилання саме на ті проекти і бібліотеки, що і в Object Browser. Звідси стає очевидним універсальний механізм підключення проектів (як шаблонів, так і документів!) до документа: це можна зробити шляхом установки посилань на потрібні вам документи і шаблони у вікні References. (Щоб не плутати наш вихідний документ DocSub.doc з шаблоном DocSub.dot, змінимо ім’я проекту шаблону на DocSubTemplate.) Тепер відзначимо кілька особливостей підключення проектів за допомогою References в середовищі VBA:



Отже, завдання організації програмної зв’язку двох документів Word вирішена. Але тут з’являється інша приваблива ідея – а чи не можна встановлювати ці зв’язки програмним способом, щоб, наприклад, вже в ході виконання програми визначати, які проекти потрібні, та динамічно встановлювати необхідні посилання? Це завдання вирішується легко!


Програмне підключення проектів


Щоб розібратися з цим питанням, відключіть всі посилання проекту ProjMain (документ DocMain), перезавантажте Word і відкрийте DocMain з приєднаним Normal (тобто все по мінімуму). Перейдіть в середу VBA.


Переглянути програмним способом повний список посилань для активного проекту, який представлений у вікні Tools / References, можна за допомогою такого коду:

Sub DocMainMacroMyRef()
‘Роздруківка посилань активного документа
Dim I%
With ActiveDocument.VBProject.References
       For i = 1 To .Count
Debug.Print “Ім’я проекту =” &. Item (i). Name
Debug.Print “Повне ім’я файлу =” &. Item (i). FullPath
          Next
    End With
End Sub

Зрозуміло, властивостей у проекту набагато більше і багато хто з них будуть корисні для використання в практичній роботі, але нам поки вистачить цих двох.


Хочу звернути увагу на те, що тут ми застосували програмну конструкцію, яка вирішує деякі практичні проблеми розробника (докладніше про це див статтю «Особливості технологій раннього і пізнього зв’язування в Visual Basic »).


Після виконання цього коду ви отримаєте такий результат у вікні Immediate:

Ім’я проекту = VBA
Повне ім’я файлу = C: Program FilesCommon FilesMicrosoft SharedVBAVBA6VBE6.DLL
Ім’я проекту = Word
Повне ім’я файлу = F: off2000OfficeMSWORD9.OLB
Ім’я проекту = stdole
Повне ім’я файлу = C: WINDOW95SYSTEMstdole2.tlb
Ім’я проекту = Office
Повне ім’я файлу = F: OFF2000OFFICEMSO9.DLL
Ім’я проекту = MSForms
Повне ім’я файлу = C: WINDOW95SYSTEMFM20.DLL
Ім’я проекту = NormalПолное ім’я файлу = C: WINDOW95Application DataMicrosoftTemplatesNormal

Для управління зв’язком проектів нам також стане в нагоді механізм доступу до списку завантажених в даний момент в середу Word документів і шаблонів

Sub DocMainMacroVBEProjects()
‘Роздруківка переліку завантажених проектів
   Dim i%With VBE.VBProjects
      For i = 1 To .Count
Debug.Print “Ім’я проекту =” &. Item (i). Name
Debug.Print “Повне ім’я файлу =” &. Item (i). FileName
       Next
    End With
End Sub

Результат виконання коду:

Ім’я проекту = Normal
Повне ім’я файлу = C: My DocumentsNormal
Ім’я проекту = ProjMain
Повне ім’я файлу = D: DocMain.doc

Звернемо увагу на велику схожість наведених вище двох фрагментів коду. Але помітна також неузгодженість в іменах однакових властивостей: в одному випадку повне ім’я файлу визначається властивістю FullPath, в іншому – FileName.


Тут слід ще раз підкреслити, що кожен документ або шаблон характеризується двома важливими ідентифікаторами – повним ім’ям файлу і ім’ям проекту. З наведених вище фрагментів зрозуміло, що на ім’я завантаженого документа можна завжди програмним чином дізнатися ім’я проекту. А за списком у вікні References (тут знаходяться проекти з унікальними іменами) можна виконати зворотну операцію. Далі ми будемо вважати, що спочатку нам відомо тільки ім’я файлу (із зазначенням повного шляху!), для якого ми відведемо змінну FileName $. Обчислюване ім’я проекту буде зберігатися в ProjectName $.


Нам також знадобиться функція, яка буде визначати, чи знаходиться вказаний файл в списку посилань активного документа:

Function TestReference(FileName$) As Object
‘Перевірка існування посилання
‘На вказаний файл з активного документа
‘ВХІД: FileName $ – повне ім’я файлу
‘ВИХІД:
‘TestReference = Nothing – ні
‘TestReference = Not Nothing – так
TestReference = Nothing ‘якщо не знайдений
With ActiveDocument.VBProject.References
For i = 1 To. Count ‘перебір всіх елементів колекції
If FileName $ =. Item (i). FullPath Then ‘знайдений
           TestReference = .Item(i): Exit For
        End If
     Next
  End With
End Function

Звичайно, можна було б задати як шуканого параметра ім’я проекту, і тоді код процедури буде виглядати набагато простіше:

Function TestReferenceNew(ProjectName$) As Object
On Error Resume Next ‘в разі помилки підключення
TestReferenceNew = Nothing ‘залишиться Nothing
     TestReferenceNew = _
           ActiveDocument.VBProject.References.Item(ProjectName$)
End Function

Але все ж ми зупинимося на першому варіанті, так як якщо ми хочемо завантажити новий файл, то ім’я його проекту нам поки просто не відомо (ми його дізнаємося в момент підключення).


Далі нам знадобиться ще пара процедур – (см. лістинг) «Процедури CreateReference і DeleteReference» – для установки і скидання посилання. Тут потрібно звернути увагу, що в CreateReference потрібно обов’язково встановити обробку помилок, поява яких дуже ймовірно, наприклад, у випадку завдання неіснуючого файла, невірного типу файлу або дублікатние імені проекту.


Увага при використанні об’єкта ActiveDocument! Тут потрібно відповісти на важливе питання – що ми розуміємо (точніше, що розуміє Word) під активним документом? При роботі в середовищі VBA може скластися враження, що активним документом є той, з проектом якого ми працюємо в даний момент. Але це не так!


Активний документ Word – той, з яким ми працювали в середовищі самого редактора перед переходом в VBA. Щоб розібратися в цьому питанні, проведіть таке дослідження. Завантажте Word і відкрийте два документи – DocMain.doc і DocSub.doc. В даному випадку прослідкуйте, щоб перший документ не містив посилань на DocSub.doc.


Перейдіть в середу VBA і створіть для першого документа таку макрокоманду:

Sub TestMacro()
MsgBox “Файл активного проекту =” & _
                       VBE.ActiveVBProject.FileName & vbCrLf & _
“Файл активного документа =” & _
                       ActiveDocument.FullName
End Sub


Перед її запуском спробуйте відповісти на питання – який документ і який проект є активним в даний момент? Відповідь щодо проекту легко отримати, поглянувши на вікно Project, – напевно там виділений зараз DocMain (ми створювали процедуру для нього). При роботі з Word 97 визначити, який документ є активним, можна – його ім’я буде видно на кнопці панелі задач. Але в Word 2000 це зробити не вдасться, так як тут кожен відкритий документ має власну кнопку, а активної кнопкою зараз є VBA.


Так от, якщо ви виконували дії у наведеній вище послідовності, то активним документом буде DocSub.doc, так як він завантажувався останнім. Проте про всяк випадок активізуйте DocSub.doc в середовищі Word, перейдіть в VBA, активізуйте проект ProjMain, запустіть на виконання макрокоманду TestMacro і переконайтеся, що імена файлів для активного шаблону і активного документа не збігаються.


Якщо ви тепер підключіть DocSub.doc до DocMain.doc за допомогою вікна References і спробуєте запустити макрокоманду DocMainMacroMyRef, то побачите, що ви отримали список посилань DocSub, а не DocMain, як хотілося б.


Звернемо увагу, що плутанина при запуску дії можлива тільки при роботі в середовищі VBA. При зверненні з середовища Word за допомогою команди Tools / Macro / Macros доступні макроси тільки активного документа, проект якого також автоматично стає активним.


Проте на цьому сюрпризи не закінчуються. Якщо ви закриєте DocMain і DocSub, а потім знову відкриєте DocMain (до якого підключений DocSub), перейдете в середу VBA і в ній запустите TestMacro, то знову виявите розбіжність активного документа та активного проекту. Справа в тому, що в момент запуску дії відбудеться автоматичне завантаження приєднаного документа DocSub.doc, який і стане активним.


Аналогічні фокуси можуть відбуватися при програмному підключенні DocSub до DocMain. При першому зверненні

Code = CreateReference&(“DocSub.doc”, ProjectName$)

все спрацює нормально – буде вироблено підключення файлу до DocMain. Однак при повторному зверненні з’явиться повідомлення про помилку. Причина цього полягає в тому, що при підключенні файлу SubDoc виконається його завантаження і він стане активним документом. При другому зверненні пошук посилань буде виконуватися для DocSub і потім піде спроба підключити цей файл до самого себе.


Вирішення цієї проблеми виглядає, здавалося б, тривіально – потрібно у всіх наведених вище програмах замінити ActiveDocument на VBE.ActiveVBProject, тобто забути про активний документі і мати справу тільки з активним проектом. Але проблема полягає в тому, що при установці нової посилання змінюється і активний проект.


Вихід тут один – стежити за тим, щоб активний документ і активний проект відповідали одному і тому ж файлу.


Якщо ж ви працюєте в середовищі VBA, то у стартовій макрокоманді можна встановити таку примусову активізацію документа:

Documents(VBE.ActiveVBProject.FileName).Activate

А для контролю за можливою зміною статусу активного документа при установці посилань можна модернізувати код процедури CreateReference наступним чином:

MyFile $ = ActiveDocument.FullName ‘запам’ятовуємо ім’я активного файлу
Set Ref = _
      ActiveDocument.VBProject.References.AddFromFile(FileName)
Documents (MyFile). Activate ‘відновлюємо активний документ і одночасно – проект

Зазначимо, що встановлення активного документа автоматично робить активним його проект. Все працює.


Завершальний кидок. Здавалося б …


Тепер ми підійшли впритул до хвилюючого моменту – власне до програмного підключенню документа DocSub.doc до документа DocMain та обігу до процедурою першого DocSubProc1. Це може виглядати наступним чином:

Sub DocMainMacro()
   Dim FileName$, Code&, ProjectName$, Say$
   FileName$ = “D:DocSub.doc”
‘1. Створення посилання на вказаний файл
   Code = CreateReference(FileName$, ProjectName$)
If ProjectName $ <> “” Then ‘підключений
     If Code = 0 Then
Say $ = “підключений зараз”
Else: Say $ = “був вже підключений”
     End If
MsgBox “Файл” & ProjectName $ & Say $ & “, _
проект = “& ProjectName $
Else ‘не вдалося підключити
MsgBox “Файл” & FileName $ & “не вдалося підключити” _
& VbCrLf & “Помилка =” & Code
     Exit Sub
   End If
   ‘
‘2. Звернення до процедури:
Call DocSubProc1 ‘при динамічному підключенні посилання
‘Тут буде помилка “Sub not defined”
‘3. Видалення (чи ні) посилання
If MsgBox (“Видалити посилання на проект” & _
                   ProjectName$, vbYesNo) = vbYes Then
DeleteReference (FileName $) ‘видалити посилання
   End If
End Sub

Здавалося б, завдання вирішене, але тут ми зіткнемося ще з однією перешкодою. Така конструкція буде працювати, тільки якщо установка посилання на DocSub вже була виконана перед запуском дії (точніше, проекту DocMain). А при динамічному підключенні файлу буде видана помилка: не визначена процедура DocSubProc1. Тут можна застосувати хитрість, замінивши пряме звернення до цієї процедури викликом проміжної підпрограми:

‘2. Звернення до проміжної процедурою:
Call MyDocSubProc1

Sub MyDocSubProc1()
   Call DocSubProc1
End Sub

Однак такий варіант буде працювати тільки при установці режиму Compile On Demand (вкладка General вікна Tools / Options), що я як раз не дуже раджу робити, особливо при налагодженні програми (докладніше див статтю «Особливості технологій раннього і пізнього зв’язування в Visual Basic» в цьому номері).


Використання властивості Run для зв’язку проектів


Проблема обігу до процедур динамічно викликаються проектів може бути вирішена за допомогою методу Run. Особисто мені свого часу здалося досить дивним сама наявність цього методу, так як звернення до макрокоманді

Call MyProject.MyModule.MyProcedure

і

Application.Run “MyProject.MyModule.MyProcedure”

абсолютно ідентичні за змістом. Але насправді між ними спостерігаються досить істотні відмінності, коли йдеться про спільну роботу проектів, і в цьому треба розібратися. Специфіка методу Run (об це не говориться в документації, ці висновки зроблені в ході експериментів і потребують більш ретельному вивченні) полягає в наступному:


Application.Run “‘DocSub.doc’!.SubModule.DocSubProc1”

З урахуванням цього звернення до процедури завантаженого (!) Документа виглядає наступним чином:

MyFile $ = ActiveDocument.FullName ‘запам’ятовуємо ім’я’ активного файлу
Documents (FileName $). Activate ‘новий активний документ
   Application.Run ProjectName$ + “.SubModule.DocSubProc1”
Documents (My File). Activate ‘відновлюємо активні’ документ і проект

Тепер про відмінності Word 97 і 2000. В Word 97 можна було звертатися тільки до макрокомандам, в Word 2000 – до будь-яких глобальних процедур модулів коду, тобто передавати параметри в підпрограми і функції. Так що в Word 2000 можна звернутися до процедури DocSubProc2, яку ми написали на самому початку цієї статті. Але звернення це виглядає досить дивно:

d% = 2
k% = Application.Run(“DocSubProc2”, d)

Тобто навіть до підпрограми потрібно звертатися як до функції (це цілком допустимо і в звичайних випадках, просто не дуже зрозуміло, що саме повертається в якості результату). Крім того, у мене абсолютно не вийшло використовувати ім’я проекту як уточнення координат функції (тобто не можна звертатися до функцій з дублікатние іменами).


Переваги методу Run представляються досить очевидними – можна виробляти динамічну настройку вашого проекту для виклику будь-яких проектів і їх процедур в процесі роботи програми, не побоюючись проблем з компіляцією коду та невизначеністю зовнішніх посилань. Наприклад, користувач може ввести з клавіатури ім’я документа, модуля та процедури:

FileName = Input Box (“Введіть ім’я документа”)
ModuleName = InputBox (“Введіть ім’я модуля”)
ProcName = InputBox (“Введіть ім’я макрокоманди”)
‘1. Якщо документ не завантажений – завантажити
‘2. Зробити його активним
‘3. Визначити ім’я його проекту
Application.Run ProjectName & “.” & ModuleName & “.” & ProcName

Звернення до VBA-проектам з VB-проекту


Якщо для VBA можна використовувати два способи звернення до процедур зовнішніх проектів, то для VB-проектів варіант тільки один – використання методу Run. Ось як це може виглядати при зверненні до процедури DocSubProc1 документа DocSub.doc в Visual Basic:

Dim oWord As Object
‘Створюємо екземпляр програми
Set oWord = CreateObject(“Word.Application”)
oWord.Documents.Open “d: docsub.doc” ‘відкриваємо документ
‘Звертаємося до його макрокоманді
oWord.Run “ProjSub.SubModule.DocSubProc1”
oWord.ActiveDocument.Close
oWord.Quit
Set oWord = Nothing

На жаль, мушу зазначити, що звернення до підпрограми DocSubProc2 з передачею параметрів у мене не вийшло.


До речі, в середовищі VB також можна здійснювати динамічне підключення ActiveX DLL, тобто програмним способом робити посилання, звичайно що виконуються у вікні Project / References. Для цього потрібно спочатку вручну зробити посилання на Microsoft Word 9.0 Object Library, щоб отримати доступ до об’єкта VBE (не дуже зрозуміло, чому такий глобальний об’єкт знаходиться в бібліотеці окремого додатка, а не в Office Object Library), і виконати, наприклад, такий код:

VBE.ActiveVBProject.References.AddFromFile “c:window95systemmsbind.dll”

Висновок


З усього сказаного вище можна зробити такий висновок: для звернення до програмного коду зовнішнього документа або шаблона Word існує два методи:



  1. Пряме звернення до процедури Call SomeProcedure. Для цього необхідно встановити в основному документі посилання на допоміжний. Зробити це можна за допомогою трьох варіантів.

    1. Підключити шаблон за допомогою вікна Template and Add-Ins в середовищі Word.
    2. Підключити будь шаблон або документ (але з ім’ям проекту) за допомогою вікна Tools / References в середовищі VBA.
    3. Програмно підключити проект. Але в цьому випадку виникають проблеми з невизначеністю посилань, які можна вирішити, встановивши режим компіляції Compile On Demand (Tools / Options / General).
    4. Список всіх доступних проектів для даного документа видно в його рядку References у вікні Project.

  2. Використання методу Run, за допомогою якого можна звернутися до макрокомандам (в Word 2000 – по всьому глобальним процедурам) активного документа (його можна динамічно встановлювати заново) і всіх глобальних шаблонів. Цей же метод дозволяє звертатися до функцій Word-проектів з VB-додатки.
  3. Я щиро дякую читачів, які змогли дістатися до кінця цієї статті. Її поява була пов’язана зі спробою відповіді на запитання читача: «навіщо потрібен метод Run». І ось що з цього вийшло …
  4. Зрозуміло, що MS Office 2000 володіє значними можливостями щодо створення систем на основі роботи взаємопов’язаних документів та їх проектів. Але все ж таки поки цей механізм представляється досить заплутаним і не до кінця відпрацьованим. Наприклад, я не згадував, що деякі властивості, що з’являються в підказках, просто не працюють. І зараз, після кількох днів боротьби з об’єднанням проектів, мені не зрозумілий відповідь на таке питання: навіщо взагалі потрібен механізм програмного підключення проектів, якщо в цьому випадку не можна використовувати пряме звернення до процедур (якщо тільки не відключений режим Compile On Demand), а для застосування більш універсального методу Run створювати посилання взагалі не потрібно?

Лістинг. Процедури CreateReference і Delete Reference

Function CreateReference&(FileName$, ProjectName$)
Створення посилання на вказаний файл
ВХІД: FileName $ – ім’я файлу
ВИХІД:
CreateReference & = 0 – файл підключений
= -1 – Було приєднано
ProjectName $ – ім’я проекту
= Інше – код помилки
    (ProjectName$ = “”
   Dim Ref As Object
On Error GoTo CreateReferenceError
   Set Ref = TestReference(FileName$)
If Ref Is Nothing Then підключаємо файл
     Set Ref = ActiveDocument.VBProject.References.AddFromFile(FileName)
     CreateReference = 0
Else вже підключений
     CreateReference = -1
   End If
визначаємо ім’я проекту
ProjectName $ = Ref.Name пізніше зв’язування!
Exit Function

CreateReferenceError: помилка при підключенні
наприклад, нелегальний тип файлу або дублікатние ім’я проекту
CreateReference = Err
ProjectName$ = “”
End Function
Function DeleteReference(FileName$) As Boolean
Видалення посилання на вказаний файл
ВХІД: FileName $ – ім’я файлу
ВИХІД: DeleteReference = True – посилання була
= False – посилання не було
Dim Ref As Object
Set Ref = TestReference(FileName$)
If Not (Ref Is Nothing) Then відключаємо посилання
ActiveDocument.VBProject.References.Remove Ref
End If
DeleteReference = Not (Ref Is Nothing)
End Function


Схожі статті:


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

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*