Здравствуйте, Disa, Вы писали:
D>Вот я написал Add-in и он работает в ворде2000 и выше а вот в 97 не хочет работать. D>Вопрос: Ворд 97 поддерживает Add-in если да то какая разница в реализации для Ворда2000? D>или просто поясните ситуацию
Дело в том, что Office97 вообще не поддерживает COM Add-Ins, в частности, в нем не реализован интерфейс IDTExtensibility2, который позволяет внешним программам встраиваться в приложения Office. Ну не то, чтобы совсем не позволяет, просто COM Add-Ins не грузятся автоматически при запуске, то есть мы не можем использовать COM расширения напрямую. Но нам никто не мешает загрузить его вручную и передать ему объект Application!
Некоторые офисные приложения поддерживают глобальные макросы AutoXXX, конкретно для Ворда — это AutoExec(), AutoNew(), AutoOpen(), AutoClose() и AutoExit(), которые вызываются автоматически. Если тебя интересует только Ворд, то объясняю что нужно делать для Ворда:
1. Создай шаблон (*.dot)
2. Открой редактор VBA и создай следующие макросы
Dim o As Application
Dim obj As Object
Sub AutoExec()
Set obj = CreateObject("_ИМЯ_ТВОЕГО_ОБЪЕКТА_")
Set o = ThisDocument.Application
obj.Initialize o
End Sub
Sub AutoExit()
If Not obj Is Nothing Then
obj.UnInitialize
End If
Set obj = Nothing
Set o = Nothing
End Sub
3. Помести этот шаблон в папку Startup и проверь чтобы было разрешено выполнение макросов.
4. Создай у себя в коде методы Initialize и UnInitialize, в который выполни необходимые действия. Например так:
STDMETHODIMP CWTWordAddin::Initialize(IDispatch *Application)
{
CComQIPtr<_Application> pApp(Application);
ATLASSERT(pApp);
if( pApp == NULL )
return S_FALSE;
// далее делай все как обычно
.....
}
P.S. В Office97 ты не сможешь поймать события от кнопок меню и тулбаров Поэтому тебе придется организовавать обработку команд через макросы, но это уже тема отдельного вопроса.
В общем при помощи вышеописанных действий (с отличиями в использовании автомакросов) у меня удалось заставить заработать Add-in в Word97, Excel97, PowerPoint97. В Outlook97 и Access97 пока не получилось.
Re[6]: Add-in в Ворде 2000 работает, а в Ворде97 нет!!!!
Здравствуйте, globus, Вы писали:
G>Здравствуйте, Dmitriy Yakovlev, по ходу приспосабливания своего аддина под Ворд появились новые к Вам вопросы. G>В своем проекте подключаю с помощью директивы #import нужную вордовскую тайп либу (MSWORD.OLB). Ну и работаю через смарт-поинтеры. Так мне проще Возникла одна ситуация, ниже кусок кода:
G>
G>В ХР офисе на этом месте все нормально, в 97 spLink не NULL (смотрю через Watch m_pInterface = 0x02e5973c и все вроде на месте). cnt = 17 (17 гиперлиннок в документе). G>И в ДебагВью вижу:
G>
G>First-chance exception at 0x00000000 in WINWORD.EXE: 0xC0000005: Access violation reading location 0x00000000.
G>First-chance exception at 0x7c81eb33 in WINWORD.EXE: 0x80010105: The server threw an exception.
G>
G>Это hr в Watch-е
G>
G>hr 0x80010105 The server threw an exception. HRESULT
G>
G>Тут я подумал, что нельза наверное подключать ТайпЛибы от 2000 офиса 97 офису. Если так, то к Вам вопрос — ка тогда быть, делать ли отдельно для 97 офиса все? я видел в Ваших предыдущих постах код:
G>значит у Вас отдельный билд для 97 офиса. G>И Вы так же само подключаете ТайпЛибы (через #define __OFFICE_97) ? G>Я думаю Вы поняли мою проблему, в двох словах — Как надо сделать чтобы работало и в 2000 и в 97 офисе. Но если другие тайплибы, то ведь код совсем другой получется — это ж надо будет с другого неймспейса выбирать интерфейсы. Или возможно, Вы сразу ОЛБ 8 версии подключали и таким образом у Вас работает аддин везде. Да если это так, прийдется переписывать ух-как не хочется то G>Уже уверен на 90% что Вы наверное подключали msword8.olb И зачем я 2000 то подключал ....
G>Заранее Вам благодарен!!!
Да Вы абсолютно правы!
У меня есть возможность делать для каждой версии офиса свой билд. Хотя реально для 2000, XP и 2003 я использую один и тот же билд с тайплибами от 2000. А вот для офиса 97 у меня отдельный билд с тайплибами именно от 97 офиса. Насчет совсем другого кода — это громко сказано! на самом деле там набор объектов и методов практически один в один такой же как и в 2000 и некоторые отличия элементарно поправляются при помощи @ifdef...#endif, я и сам не знаю почему я решил делать отдельный билд, просто показалось что так лучше будет. Проект у меня довольно большой, но чтобы все компилировалось под 97 у меня ушло ну может быть день работы. Основное время ушло на переделку кода для MS Access (работа с Reports), хотя у меня так и не получилось подключить его позже
Я Вам рекомендую делать также 2 билда, так как если все сделать на тайплибах от 97 то работать оно будет везде! но вот только придется работать через макросы!!! А это очень существенное ограничение, ведь юзер может настроить политику безопасности так, что макросы будут отключены и тогда ...
А неймспейсы там отличаются только некоторыми классами, я воспользовался директивой #define чтобы привести их название к такому же названию как и в 2000 и выше, поэтому ничего переделавать мне не пришлось!
Здравствуйте, globus, Вы писали:
G>Здраствуйте Dmitriy Yakovlev & All. Есть у меня COM-аддин для Word, Excel & PowerPoint. Я понял как передать Application в Ворд 97, а как с меню и тулбаром. Я добавляю их в своем COM сервере, неужели надо делать тоже самое только на ВБА и задавать OnAction для меню и тулбара. Вы, Dmitriy Yakovlev, в своем посте написали что Вам удалось заставить заработать Add-in в Word97, Excel97, PowerPoint97. Плз. поделитесь инфой м если можно куски кода ка поймать события от кнопок меню и тулбаров в 97 офисе
G>Надеюсь на Вашу помощь, заранее благодарен!!!
Нет, VBA я использую по минимуму и все делаю в COM-аддине, чтобы избежать больших различий в реализации под разные версии офиса.
Если Вы разобрались как подключиться к Excel & PowerPoint, тогда мне осталось рассказать как обрабатывать команды. Это намного проще, чем можно себе представить: OnAction можно задать в COM-аддине, а в макросе — организовать обратную связь.
При создании команды нужно не забыть указать OnAction, а также TAG, по которому мы позднее будем идентифицировать команду.
Дополнительно к автомакросам нужно добавить еще один метод OnCmd, который мы указали в OnAction для команды. (Можно использовать любое название для этого метода). В нем мы можем получить тэг вызванной команды, ну а дальше оповестить наш аддин о команде уже дело техники
Sub OnCmd()
If Not obj Is Nothing Then
obj.DoCmd97 CommandBars.ActionControl.Tag
End If
End Sub
DoCmd97 – это сом-метод в моем сом-аддине, из которого передается управление в общий метод обработки команды по ее ТЭГу.
Здраствуйте Dmitriy Yakovlev & All. Есть у меня COM-аддин для Word, Excel & PowerPoint. Я понял как передать Application в Ворд 97, а как с меню и тулбаром. Я добавляю их в своем COM сервере, неужели надо делать тоже самое только на ВБА и задавать OnAction для меню и тулбара. Вы, Dmitriy Yakovlev, в своем посте написали что Вам удалось заставить заработать Add-in в Word97, Excel97, PowerPoint97. Плз. поделитесь инфой м если можно куски кода ка поймать события от кнопок меню и тулбаров в 97 офисе
Надеюсь на Вашу помощь, заранее благодарен!!!
Re[3]: Add-in в Ворде 2000 работает, а в Ворде97 нет!!!!
Здравствуйте, Dmitriy Yakovlev, Вы писали:
DY>Здравствуйте, globus, Вы писали:
G>>Здраствуйте Dmitriy Yakovlev & All. Есть у меня COM-аддин для Word, Excel & PowerPoint. Я понял как передать Application в Ворд 97, а как с меню и тулбаром. Я добавляю их в своем COM сервере, неужели надо делать тоже самое только на ВБА и задавать OnAction для меню и тулбара. Вы, Dmitriy Yakovlev, в своем посте написали что Вам удалось заставить заработать Add-in в Word97, Excel97, PowerPoint97. Плз. поделитесь инфой м если можно куски кода ка поймать события от кнопок меню и тулбаров в 97 офисе
G>>Надеюсь на Вашу помощь, заранее благодарен!!!
DY>Нет, VBA я использую по минимуму и все делаю в COM-аддине, чтобы избежать больших различий в реализации под разные версии офиса. DY>Если Вы разобрались как подключиться к Excel & PowerPoint, тогда мне осталось рассказать как обрабатывать команды. Это намного проще, чем можно себе представить: OnAction можно задать в COM-аддине, а в макросе — организовать обратную связь.
DY>При создании команды нужно не забыть указать OnAction, а также TAG, по которому мы позднее будем идентифицировать команду. DY>
DY>Дополнительно к автомакросам нужно добавить еще один метод OnCmd, который мы указали в OnAction для команды. (Можно использовать любое название для этого метода). В нем мы можем получить тэг вызванной команды, ну а дальше оповестить наш аддин о команде уже дело техники DY>
Sub OnCmd()
DY> If Not obj Is Nothing Then
DY> obj.DoCmd97 CommandBars.ActionControl.Tag
DY> End If
DY>End Sub
DY>DoCmd97 – это сом-метод в моем сом-аддине, из которого передается управление в общий метод обработки команды по ее ТЭГу. DY>
Здравствуйте, Dmitriy Yakovlev, Вы писали:
DY>Здравствуйте, Disa, Вы писали:
DY>1. Создай шаблон (*.dot)
DY>2. Открой редактор VBA и создай следующие макросы
DY>
DY>Dim o As Application
DY>Dim obj As Object
DY>Sub AutoExec()
DY> Set obj = CreateObject("_ИМЯ_ТВОЕГО_ОБЪЕКТА_")
DY> Set o = ThisDocument.Application
DY> obj.Initialize o
DY>End Sub
DY>Sub AutoExit()
DY> If Not obj Is Nothing Then
DY> obj.UnInitialize
DY> End If
DY> Set obj = Nothing
DY> Set o = Nothing
DY>End Sub
DY>
DY>3. Помести этот шаблон в папку Startup и проверь чтобы было разрешено выполнение макросов.
DY>4. Создай у себя в коде методы Initialize и UnInitialize, в который выполни необходимые действия. Например так:
DY>
DY>STDMETHODIMP CWTWordAddin::Initialize(IDispatch *Application)
DY>{
DY> CComQIPtr<_Application> pApp(Application);
DY> ATLASSERT(pApp);
DY> if( pApp == NULL )
DY> return S_FALSE;
DY> // далее делай все как обычно
DY> .....
DY>}
DY>
Сделал все как написано, и в ВБА скрипте при вызове "obj.Initialize o" выдает "Ошибка выполнения 13, Несоответствие типа"
менял "Dim o As Application" на "Dim o As Object" не помогло.
В idl у меня
Здравствуйте, globus, Вы писали:
G>Сделал все как написано, и в ВБА скрипте при вызове "obj.Initialize o" выдает "Ошибка выполнения 13, Несоответствие типа" G>менял "Dim o As Application" на "Dim o As Object" не помогло. G>В idl у меня
G>
Dim o As Application
Dim obj As Object
Sub AutoExec()
Set obj = CreateObject("WTOfficeAddin.WTWordAddin.1")
Set o = ThisDocument.Application
obj.Init o
End Sub
Sub AutoExit()
If Not obj Is Nothing Then
obj.Uninit
End If
Set obj = Nothing
Set o = Nothing
End Sub
Sub OnCmd()
If Not obj Is Nothing Then
obj.DoCmd97 CommandBars.ActionControl.Tag
End If
End Sub
Re[3]: Add-in в Ворде 2000 работает, а в Ворде97 нет!!!!
Здравствуйте, Dmitriy Yakovlev, большое спасибо за Вашу поддержку, вот написал
Dim o As Application // или Object - все равно
Sub AutoExec()
Set obj = CreateObject("PXCOfficeAddin.Addin")
Set o = ThisDocument.Application
obj.Initialize o.Application
End Sub
Так работает Вот не понимаю только почему так работает а так
obj.Initialize o
не работает...
Re[4]: Add-in в Ворде 2000 работает, а в Ворде97 нет!!!!
Здравствуйте, globus, Вы писали:
G>Здравствуйте, Dmitriy Yakovlev, большое спасибо за Вашу поддержку, вот написал
Всегда рад
G>
G>Dim o As Application // или Object - все равно
G>Sub AutoExec()
G> Set obj = CreateObject("PXCOfficeAddin.Addin")
G> Set o = ThisDocument.Application
G> obj.Initialize o.Application
G>End Sub
G>
G>Так работает Вот не понимаю только почему так работает а так
G>
G>obj.Initialize o
G>
G>не работает...
Ну, возможно, у нас различия в IDL. Я не особо большой спец, но могу предположить что из-за того у тебя в определении параметра IDispatch *pDisp используется [in], то на вход должен прийти readonly объект и, возможно, для полного соответствия типов тебе приходится передавать именно readonly свойство Application объекта Application. Попробуй убрать [in], посмотри что получится.
Property Application As Application
read-only
Member of Word.Application
Re[5]: Add-in в Ворде 2000 работает, а в Ворде97 нет!!!!
Здравствуйте, Dmitriy Yakovlev, Вы писали:
DY>Ну, возможно, у нас различия в IDL. Я не особо большой спец, но могу предположить что из-за того у тебя в определении
параметра IDispatch *pDisp используется [in], то на вход должен прийти readonly объект и, возможно, для полного соответствия типов тебе приходится передавать именно readonly свойство Application объекта Application. Попробуй убрать [in], посмотри что получится. DY>
DY>Property Application As Application
DY> read-only
DY> Member of Word.Application
DY>
Цетирую из книги Э.Трельсена "Модель СОМ приминение ATL 3.0": "[in] — Посылка от клиента к серверу. Клиент выделяет и освобождает память для этого параметра. Все параметры по умолчанию считаются [in], если не указано другое".
Значит проблема не в этом. Любопытно докопатся до истины, приводимый Вами код (ВБА) у всех работает, никто не жалуется, а у меня как всегда где-то чето... Офис 97 русский.
Re[5]: Add-in в Ворде 2000 работает, а в Ворде97 нет!!!!
Здравствуйте, Dmitriy Yakovlev, по ходу приспосабливания своего аддина под Ворд появились новые к Вам вопросы.
В своем проекте подключаю с помощью директивы #import нужную вордовскую тайп либу (MSWORD.OLB). Ну и работаю через смарт-поинтеры. Так мне проще Возникла одна ситуация, ниже кусок кода:
В ХР офисе на этом месте все нормально, в 97 spLink не NULL (смотрю через Watch m_pInterface = 0x02e5973c и все вроде на месте). cnt = 17 (17 гиперлиннок в документе).
И в ДебагВью вижу:
First-chance exception at 0x00000000 in WINWORD.EXE: 0xC0000005: Access violation reading location 0x00000000.
First-chance exception at 0x7c81eb33 in WINWORD.EXE: 0x80010105: The server threw an exception.
Это hr в Watch-е
hr 0x80010105 The server threw an exception. HRESULT
Тут я подумал, что нельза наверное подключать ТайпЛибы от 2000 офиса 97 офису. Если так, то к Вам вопрос — ка тогда быть, делать ли отдельно для 97 офиса все? я видел в Ваших предыдущих постах код:
значит у Вас отдельный билд для 97 офиса.
И Вы так же само подключаете ТайпЛибы (через #define __OFFICE_97) ?
Я думаю Вы поняли мою проблему, в двох словах — Как надо сделать чтобы работало и в 2000 и в 97 офисе. Но если другие тайплибы, то ведь код совсем другой получется — это ж надо будет с другого неймспейса выбирать интерфейсы. Или возможно, Вы сразу ОЛБ 8 версии подключали и таким образом у Вас работает аддин везде. Да если это так, прийдется переписывать ух-как не хочется то
Уже уверен на 90% что Вы наверное подключали msword8.olb И зачем я 2000 то подключал ....
Заранее Вам благодарен!!!
Re[7]: Add-in в Ворде 2000 работает, а в Ворде97 нет!!!!
Здравствуйте, Dmitriy Yakovlev, спасибо Вам за предыдущий пост (оценку поставил ).
Наткнулся еще на одну граблю. Для 97 офиса файл excel8.tli содержит вропер диспинтерфейса, тогда как msword8.tli и msppt8.tli — дуал интерфейса. Теперь в коде метода Init (где добавляются менюшки)
вот в этом фрагменте, при выполнении последней строки выскакикает GPF:
Run-Time Check Failure #0 - The value of ESP was not properly saved across a function call.
This is usually a result of calling a function declared with one calling convention with a function pointer declared with a different calling convention.
Теперь смотрю в Watch на spBars. Иерархия вложенности интерфейсов такова:
Заметьте Office::_IMsoDispObj, у всех других (например, из неймспейса Office) Office::_IMsoDispObj нету — m_pInterface сразу наследуется от IDispatch. но впринципе, проблемы в этом не вижу.
Теперь к импорт директиве дописую no_dual_interfaces:
Вижу что надо чтобы и в Office и в MSEXCEL была реализация либо через виртуальную таблицу (как в случае с вордом и поверпоинтом), либо же через диспинтерфейс.
В МСДН в атрибутах директивы import нашел как отключить диспинтерфейс (no_dual_interfaces), но как задать его нету. Может он установлен по умолчанию, но почему тода для екселя реализация через диспинтерфейс?
Отсюда вижу один выход, задать всем в #import атрибут no_dual_interfaces. Но это ж тормозить будет по сравнению с виртуальной таблицей.
В итоге парочка к Вам вопросов, Dmitriy Yakovlev. Посмотрите на Ваш вропер(файл excel8.tli), Ваша реализация случайно не через диспинтерфейс?
И все остальное в том же духе — через вызов _com_dispatch_method. У Вас также? Если да то как У вас тогда работает, если mso97.tli ведь через виртуальную таблицу?
Я возможно не очень доступно выражаю свои вопросы, и может кое-что не коректно, так как с СОМ-ом я осторожно и "на Вы" но думаю, что моя проблема Вам понятна.
Заранее благодарен!!!
Re[8]: Add-in в Ворде 2000 работает, а в Ворде97 нет!!!!
Решил все-таки запостить в старую тему ответ (или, может, не совсем ответ, а метод).
После долгих исканий и экспериментов результатом использования интерфейсов MSOffice с целью automation были следующие:
Ошибка: "fatal error LNK1179: invalid or corrupt file: duplicate COMDAT
'<identifier name>'"
обходится двумя путями:
1) разнести #import разных либ в *.h и в *.cpp (данный метод не подходит для случая, когда в *.h нужно продефайнить типы)
2) убрать в одной из импортируемых либ "named_guids". Если это можно сделать безболезненно — проблема решена, если
эти гуиды нужны в удобочитаемом виде — придется скопировать их определения из tlh в отдельный хедер и включать его
по необходимости.
Далее:
случайным брожением по tlh-кам было выяснено, что ошибка: "Run-Time Check Failure #0 — The value of ESP was not properly saved across a function call.
This is usually a result of calling a function declared with one calling convention with a function pointer declared with a different calling convention."
вылезает в сзязи с тем, что многие методы интерфейсов получают параметрами (возвращают) не указатели на интерфейс, как это описано в
OLE/COM viewer'е, а указатели на IDispatch, от которого наследуется данный интерфейс.
Вариантов решения, опять-таки 2:
1) Использовать Invoke пришедшего указателя на IDispatch нужного интерфейса.
Для некоторых методов это единственное решение, т.к. даже в tlh врапперы соответствующих
методов описаны как принимающие VARIANT * или просто VARIANT.
2) Для некоторых методов достаточно сделать явное получение указателя на необходимый интерфейс с помощью
QueryInterface пришедшего (IDispatch*) указателя.
Вроде все (пока что) .
Как что еще накопаю в дальнейшем — обязательно отсвищу.
Удачи всем в юзании MSOffice automation и всего, что с ним связано.