Add-in в Ворде 2000 работает, а в Ворде97 нет!!!!
От: Dmitriy Yakovlev Украина www.prof-uis.com
Дата: 24.09.04 07:19
Оценка: 13 (3)
#Имя: FAQ.com.office.addins97
Здравствуйте, 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 нет!!!!
От: Dmitriy Yakovlev Украина www.prof-uis.com
Дата: 18.10.04 13:28
Оценка: 12 (2)
Здравствуйте, globus, Вы писали:

G>Здравствуйте, Dmitriy Yakovlev, по ходу приспосабливания своего аддина под Ворд появились новые к Вам вопросы.

G>В своем проекте подключаю с помощью директивы #import нужную вордовскую тайп либу (MSWORD.OLB). Ну и работаю через смарт-поинтеры. Так мне проще Возникла одна ситуация, ниже кусок кода:

G>
G>MSWORD::_ApplicationPtr spApp = m_spApp;
G>MSWORD::_DocumentPtr spDoc = spApp->GetActiveDocument();
G>_variant_t vt(1);
G>int cnt = spDoc->GetHyperlinks()->GetCount();
G>MSWORD::HyperlinkPtr spLink = spDoc->GetHyperlinks()->Item(&vt);
G>// сначада использовал 
G>// bstr_t bstrAddress = GetAddress();
G>BSTR bstr = NULL;
G>HRESULT hr = spLink->get_Address(&bstr);
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>
G>#ifdef __OFFICE_97
DY>>    pCBButton->OnAction = _bstr_t(_T("OnCmd"));
DY>>#endif // __OFFICE_97
G>


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 и выше, поэтому ничего переделавать мне не пришлось!

#if (defined __OFFICE_97) // Office 97

    #import "D:\Program Files\Common Files\Designer\msaddndr.dll" \
        raw_interfaces_only, \
        raw_native_types, \
        no_namespace, \
        named_guids 

    #import "D:\Program Files\Microsoft Office\Office\mso97.dll" \
        rename_namespace("Office") 

    #import "D:\Program Files\Common Files\Microsoft Shared\VBA\VBEEXT1.olb"

    #define _CommandBarButtonEvents VBIDE::_CommandBarControlEvents
    #define _CommandBarsEvents VBIDE::CommandBarEvents
    #define _CommandBarsPtr Office::CommandBarsPtr
    #define _CommandBarButtonPtr Office::CommandBarButtonPtr

    // access
    #pragma message("   Linking with MS Access")
    #import "D:\Program Files\Microsoft Office\Office\msacc8.olb" \
        raw_interfaces_only \
        rename("SHIFT_MASK","SHIFT_MASK_X") \
        rename("CTRL_MASK","CTRL_MASK_X") \
        rename("ALT_MASK","ALT_MASK_X") \
        rename("LEFT_BUTTON","LEFT_BUTTON_X") \
        rename("RIGHT_BUTTON","RIGHT_BUTTON_X") \
        rename("MIDDLE_BUTTON","MIDDLE_BUTTON_X") \
        rename("Property","IDispatch")
    #import "d:\Program Files\Common Files\Microsoft Shared\dao\dao360.dll" \
        rename("EOF","_EOF") 

    // excel
    #pragma message("   Linking with MS Excel")
    #import "D:\Program Files\Microsoft Office\Office\excel8.olb" \
        rename("DialogBox","_DialogBox"), \
        rename("RGB","_RGB") 

    // outlook
    #pragma message("   Linking with MS Outlook")
    #import "D:\Program Files\Microsoft Office\office\msoutl8.olb" \
        rename("IPage","IDispatch") \
        rename("Font","IFont")

    // power point
    #pragma message("   Linking with MS PowerPoint")
    #import "D:\Program Files\Microsoft Office\office\msppt8.olb"

    // word
    #pragma message("   Linking with MS Word")
    #import "D:\Program Files\Microsoft Office\office\msword8.olb" \
        rename("ExitWindows", "_ExitWindows") 

#endif
Re[2]: Add-in в Ворде 2000 работает, а в Ворде97 нет!!!!
От: Dmitriy Yakovlev Украина www.prof-uis.com
Дата: 12.10.04 10:57
Оценка: 2 (1)
Здравствуйте, 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, по которому мы позднее будем идентифицировать команду.
pCBButton ->Tag = _bstr_t(sTag);
#ifdef __OFFICE_97
    pCBButton->OnAction = _bstr_t(_T("OnCmd"));
#endif // __OFFICE_97

Дополнительно к автомакросам нужно добавить еще один метод OnCmd, который мы указали в OnAction для команды. (Можно использовать любое название для этого метода). В нем мы можем получить тэг вызванной команды, ну а дальше оповестить наш аддин о команде уже дело техники
Sub OnCmd()
    If Not obj Is Nothing Then
        obj.DoCmd97 CommandBars.ActionControl.Tag
    End If
End Sub

DoCmd97 – это сом-метод в моем сом-аддине, из которого передается управление в общий метод обработки команды по ее ТЭГу.
STDMETHODIMP CWTWordAddin::DoCmd97(BSTR Tag)
{
    bool bRet = false;
    if( m_pWTToolbar != NULL )
        bRet = m_pWTToolbar->OnDoCmd( Tag );

    return bRet ? S_OK : S_FALSE;
}

Вот и все. Данная реализация одинакова для Word, Excel и PowerPoint.
Удачи!
Add-in в Ворде 2000 работает, а в Ворде97 нет!!!!
От: Disa Россия  
Дата: 23.09.04 13:30
Оценка:
Вот я написал Add-in и он работает в ворде2000 и выше
а вот в 97 не хочет работать.

Вопрос: Ворд 97 поддерживает Add-in если да то какая разница в реализации для Ворда2000?

или просто поясните ситуацию
Re[2]: Add-in в Ворде 2000 работает, а в Ворде97 нет!!!!
От: Disa Россия  
Дата: 24.09.04 16:19
Оценка:
Здравствуйте, Dmitriy Yakovlev, Вы писали:

ВСЕ ЯСНО!!!

большое спасибо за подробный ответ
Re: Add-in в Ворде 2000 работает, а в Ворде97 нет!!!!
От: globus  
Дата: 12.10.04 08:30
Оценка:
Здраствуйте 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 нет!!!!
От: globus  
Дата: 12.10.04 13:29
Оценка:
Здравствуйте, 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>
pCBButton ->Tag = _bstr_t(sTag);
DY>#ifdef __OFFICE_97
DY>    pCBButton->OnAction = _bstr_t(_T("OnCmd"));
DY>#endif // __OFFICE_97

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>
STDMETHODIMP CWTWordAddin::DoCmd97(BSTR Tag)
DY>{
DY>    bool bRet = false;
DY>    if( m_pWTToolbar != NULL )
DY>        bRet = m_pWTToolbar->OnDoCmd( Tag );

DY>    return bRet ? S_OK : S_FALSE;
DY>}

DY>Вот и все. Данная реализация одинакова для Word, Excel и PowerPoint.
DY>Удачи!

Спасибо, буду пробовать
Re: Add-in в Ворде 2000 работает, а в Ворде97 нет!!!!
От: globus  
Дата: 14.10.04 15:20
Оценка:
Здравствуйте, 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 у меня


interface IAddin : IDispatch
{
    [id(1),helpstring("method Init")] HRESULT  Initialize([in] IDispatch *pDisp);
    [id(2),helpstring("method Uninit")] HRESULT  Uninitialize([in] IDispatch *pDisp);
};
Re[2]: Add-in в Ворде 2000 работает, а в Ворде97 нет!!!!
От: Dmitriy Yakovlev Украина www.prof-uis.com
Дата: 14.10.04 15:33
Оценка:
Здравствуйте, globus, Вы писали:

G>Сделал все как написано, и в ВБА скрипте при вызове "obj.Initialize o" выдает "Ошибка выполнения 13, Несоответствие типа"

G>менял "Dim o As Application" на "Dim o As Object" не помогло.
G>В idl у меня

G>
G>interface IAddin : IDispatch
G>{
G>    [id(1),helpstring("method Init")] HRESULT  Initialize([in] IDispatch *pDisp);
G>    [id(2),helpstring("method Uninit")] HRESULT  Uninitialize([in] IDispatch *pDisp);
G>};
G>



Моя реализация выглядит так, у меня все работает, проверь у себя, возможно там какая-то мелкая ошибочка.

interface IWTWordAddin : IDispatch
{
    [id(1), helpstring("method Init")] HRESULT Init(IDispatch * Application);
    [id(2), helpstring("method Uninit")] HRESULT Uninit();
    [id(3), helpstring("method DoCmd97")] HRESULT DoCmd97(BSTR Tag );
};

public:
STDMETHOD(DoCmd97)(BSTR Tag );
STDMETHOD(Uninit)();
STDMETHOD(Init)(IDispatch * Application);

////

STDMETHODIMP CWTWordAddin::Init(IDispatch *Application)
{
    // ...
}

STDMETHODIMP CWTWordAddin::Uninit()
{
    // ...
}

STDMETHODIMP CWTWordAddin::DoCmd97(BSTR Tag)
{
    // ...
}

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 нет!!!!
От: globus  
Дата: 15.10.04 11:07
Оценка:
Здравствуйте, 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 нет!!!!
От: Dmitriy Yakovlev Украина www.prof-uis.com
Дата: 15.10.04 11:35
Оценка:
Здравствуйте, 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 нет!!!!
От: globus  
Дата: 15.10.04 13:14
Оценка:
Здравствуйте, 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 нет!!!!
От: globus  
Дата: 18.10.04 10:52
Оценка:
Здравствуйте, Dmitriy Yakovlev, по ходу приспосабливания своего аддина под Ворд появились новые к Вам вопросы.
В своем проекте подключаю с помощью директивы #import нужную вордовскую тайп либу (MSWORD.OLB). Ну и работаю через смарт-поинтеры. Так мне проще Возникла одна ситуация, ниже кусок кода:

MSWORD::_ApplicationPtr spApp = m_spApp;
MSWORD::_DocumentPtr spDoc = spApp->GetActiveDocument();
_variant_t vt(1);
int cnt = spDoc->GetHyperlinks()->GetCount();
MSWORD::HyperlinkPtr spLink = spDoc->GetHyperlinks()->Item(&vt);
// сначада использовал 
// bstr_t bstrAddress = GetAddress();
BSTR bstr = NULL;
HRESULT hr = spLink->get_Address(&bstr);


В ХР офисе на этом месте все нормально, в 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 офиса все? я видел в Ваших предыдущих постах код:


#ifdef __OFFICE_97
DY>    pCBButton->OnAction = _bstr_t(_T("OnCmd"));
DY>#endif // __OFFICE_97


значит у Вас отдельный билд для 97 офиса.
И Вы так же само подключаете ТайпЛибы (через #define __OFFICE_97) ?
Я думаю Вы поняли мою проблему, в двох словах — Как надо сделать чтобы работало и в 2000 и в 97 офисе. Но если другие тайплибы, то ведь код совсем другой получется — это ж надо будет с другого неймспейса выбирать интерфейсы. Или возможно, Вы сразу ОЛБ 8 версии подключали и таким образом у Вас работает аддин везде. Да если это так, прийдется переписывать ух-как не хочется то
Уже уверен на 90% что Вы наверное подключали msword8.olb И зачем я 2000 то подключал ....

Заранее Вам благодарен!!!
Re[7]: Add-in в Ворде 2000 работает, а в Ворде97 нет!!!!
От: globus  
Дата: 22.10.04 12:44
Оценка:
Здравствуйте, Dmitriy Yakovlev, спасибо Вам за предыдущий пост (оценку поставил ).

Наткнулся еще на одну граблю. Для 97 офиса файл excel8.tli содержит вропер диспинтерфейса, тогда как msword8.tli и msppt8.tli — дуал интерфейса. Теперь в коде метода Init (где добавляются менюшки)

MSEXCEL::_ApplicationPtr spExcelApp(Application);
Office::CommandBarsPtr spBars = spExcelApp->GetCommandBars();
Office::CommandBarPtr spMenuBar = spBars->GetActiveMenuBar();


вот в этом фрагменте, при выполнении последней строки выскакикает 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. Иерархия вложенности интерфейсов такова:

+ spBars
+ m_pInterface
+ Office::_IMsoDispObj
+ IDispatch
+ IUnknown

Заметьте Office::_IMsoDispObj, у всех других (например, из неймспейса Office) Office::_IMsoDispObj нету — m_pInterface сразу наследуется от IDispatch. но впринципе, проблемы в этом не вижу.

Теперь к импорт директиве дописую no_dual_interfaces:

#import <MSO97.DLL> rename_namespace("Office"), rename("RGB","MsoRGB"), rename("DocumentProperties", "MsoDocumentProperties"), named_guids, no_dual_interfaces

Теперь в excel8.tli и в mso97.tli — реализация через диспинтерфейс и код

MSEXCEL::_ApplicationPtr spExcelApp(Application);
Office::CommandBarsPtr spBars = spExcelApp->GetCommandBars();
Office::CommandBarPtr spMenuBar = spBars->GetActiveMenuBar();


работает.

Вижу что надо чтобы и в Office и в MSEXCEL была реализация либо через виртуальную таблицу (как в случае с вордом и поверпоинтом), либо же через диспинтерфейс.

В МСДН в атрибутах директивы import нашел как отключить диспинтерфейс (no_dual_interfaces), но как задать его нету. Может он установлен по умолчанию, но почему тода для екселя реализация через диспинтерфейс?

Отсюда вижу один выход, задать всем в #import атрибут no_dual_interfaces. Но это ж тормозить будет по сравнению с виртуальной таблицей.

В итоге парочка к Вам вопросов, Dmitriy Yakovlev. Посмотрите на Ваш вропер(файл excel8.tli), Ваша реализация случайно не через диспинтерфейс?

У меня начинается:

#pragma implementation_key(1)
inline IDispatchPtr MSEXCEL::Adjustments::GetApplication ( ) {
    IDispatch * _result = 0;
    _com_dispatch_method(this, 0x60020000, DISPATCH_PROPERTYGET, VT_DISPATCH, (void*)&_result, NULL);
    return IDispatchPtr(_result, false);
}


И все остальное в том же духе — через вызов _com_dispatch_method. У Вас также? Если да то как У вас тогда работает, если mso97.tli ведь через виртуальную таблицу?

Я возможно не очень доступно выражаю свои вопросы, и может кое-что не коректно, так как с СОМ-ом я осторожно и "на Вы" но думаю, что моя проблема Вам понятна.

Заранее благодарен!!!
Re[8]: Add-in в Ворде 2000 работает, а в Ворде97 нет!!!!
От: FUriCK Украина  
Дата: 18.07.05 12:01
Оценка:
Решил все-таки запостить в старую тему ответ (или, может, не совсем ответ, а метод).

После долгих исканий и экспериментов результатом использования интерфейсов 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 и всего, что с ним связано.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.