Excel automation

Тема в разделе "WASM.WIN32", создана пользователем Ilgar, 21 мар 2009.

  1. Ilgar

    Ilgar New Member

    Публикаций:
    0
    Регистрация:
    21 мар 2007
    Сообщения:
    9
    День добрый уважаемые господа. Прошу помощи в решении проблемы над которой бьюсь уже несколько дней. Задача очень проста: запустить MS Excel и сделать его видимым, все остальное я сделаю сам. Проблема: есть код на C++ работает без проблем (делаю с excel все что захочу), но я не хочу C++, нужно все тоже самое только на asm.
    Ниже исходники на C++ и на asm на мой взгляд они идентичны, но сишный работает, а asm нет (Excel запускается, но видимым становиться ну совершенно не хочет) не пойму что не так.

    ############C++#############

    #include "stdafx.h"
    #include <ole2.h>
    #include <stdlib.h>


    int main()
    {
    IDispatch *pXlApp = 0;
    CLSID clsid;
    wchar_t *wbuffer = L"Visible";
    DISPID dispID = 0;
    DISPPARAMS dp = { NULL, NULL, 0, 0 };
    DISPID dispidNamed = DISPID_PROPERTYPUT;
    VARIANT parm;

    CoInitialize(NULL);
    CLSIDFromProgID(L"Excel.Application",&clsid);
    CoCreateInstance(clsid,NULL,CLSCTX_LOCAL_SERVER,IID_IDispatch,(void **)&pXlApp);

    parm.vt = VT_BOOL;
    parm.boolVal = 1;

    dp.cArgs = 1;
    dp.rgvarg = &parm;
    dp.cNamedArgs = 1;
    dp.rgdispidNamedArgs = &dispidNamed;

    pXlApp->GetIDsOfNames(IID_NULL, &wbuffer, 1, LOCALE_USER_DEFAULT, &dispID);
    pXlApp->Invoke(dispID,IID_NULL,LOCALE_SYSTEM_DEFAULT,DISPATCH_PROPERTYPUT,&dp,NULL,NULL,NULL);
    CoUninitialize();
    return 0;
    }

    ############ASM#############

    .386
    .model flat,stdcall
    option casemap:none

    include windows.inc
    include kernel32.inc
    include oaidl.inc
    include ole32.inc
    include oleaut32.inc
    includelib kernel32.lib
    includelib ole32.lib
    includelib oleaut32.lib

    main proto

    .data
    clsid CLSID <>
    IID_NULL GUID <0,0,0,<0,0,0,0,0,0,0,0>>
    IID_IDispatch GUID <000020400H,00000H,00000H,<0C0H,000H,000H,000H,000H,000H,000H,046H>>
    szExcelApp db "Excel.Application",0
    dispID DISPID 0
    pXlApp dd 0
    mtdVisible db "Visible",0
    parm VARIANTARG <>
    dsppar DISPPARAMS <0,0,0,0>
    dispidNamed DISPID DISPID_PROPERTYPUT

    .data?
    buffer db 256 dup(?)
    wbuffer db 512 dup(?)

    .const

    .code

    start:
    invoke main
    invoke ExitProcess,eax

    main proc

    invoke MultiByteToWideChar,CP_ACP,0,addr szExcelApp,-1,addr wbuffer,510
    invoke CLSIDFromProgID,addr wbuffer,addr clsid
    test eax,eax
    jne @UNINITCOM

    invoke CoInitialize,0
    test eax,eax
    js @RETURN

    invoke CoCreateInstance,addr clsid,NULL,CLSCTX_LOCAL_SERVER,addr IID_IDispatch,addr pXlApp
    test eax,eax
    jne @UNINITCOM

    mov parm.vt,VT_BOOL
    mov parm.boolVal,1

    mov dsppar.cArgs,1
    lea eax,parm
    mov dsppar.rgvarg,eax
    mov dsppar.cNamedArgs,1
    lea eax,dispidNamed
    mov dsppar.rgdispidNamedArgs,eax

    invoke MultiByteToWideChar,CP_ACP,0,addr mtdVisible,-1,addr wbuffer,510
    coinvoke pXlApp,IDispatch,GetIDsOfNames,addr IID_NULL,addr wbuffer,1,LOCALE_USER_DEFAULT,addr dispID
    coinvoke pXlApp,IDispatch,Invoke,dispID,addr IID_NULL,800h,DISPATCH_PROPERTYPUT,addr dsppar,NULL,NULL,NULL

    @UNINITCOM:
    invoke CoUninitialize

    @RETURN:
    xor eax,eax
    ret

    main endp

    end start
     
  2. MirrorBlack

    MirrorBlack Алексей

    Публикаций:
    0
    Регистрация:
    21 июн 2008
    Сообщения:
    249
    Адрес:
    Moscow
    Код даже смотреть не стал как увидел подключение oaidl.inc :)
    Запиши в него правильную структуру DISPPARAMS. В masm последние 2 прараметра WORD.
    Сам помню крыл всех х...ми :derisive:

    DISPPARAMS STRUCT DWORD
    rgvarg PVOID ?
    rgdispidNamedArgs PVOID ?
    cArgs DWORD ?
    cNamedArgs DWORD ?
    DISPPARAMS ENDS

    И не стесняйся пользоваться SysAllocString и SysFreeString
     
  3. Sol_Ksacap

    Sol_Ksacap Миша

    Публикаций:
    0
    Регистрация:
    6 мар 2008
    Сообщения:
    623
    И охота одному строки гонять? Ведь MASM уже способен здание UNICODE-приложений.

     



    Здесь должен быть указатель на массив строк, но не на массив символов, ага.
     
  4. Ilgar

    Ilgar New Member

    Публикаций:
    0
    Регистрация:
    21 мар 2007
    Сообщения:
    9
    Огромное мерси MirrorBlack, все заработало простым добавлением этой структуры :)
     
  5. MirrorBlack

    MirrorBlack Алексей

    Публикаций:
    0
    Регистрация:
    21 июн 2008
    Сообщения:
    249
    Адрес:
    Moscow
    Ilgar
    Я не понял шутки юмора...
    Sol_Ksacap Абсолютно прав на счёт addr wbuffer.
    Правильно записать так:
    coinvoke pXlApp,IDispatch,GetIDsOfNames,addr IID_NULL,addr pBuf, 1, LOCALE_USER_DEFAULT, addr dispID

    pBuf dd offset szCommand

    szCommand WCHAR L(<XXX\0>)

    xxx - это не обозначение фильмов для взрослых...

    Посмотри это:
    http://www.ironahot.idknet.com/
     
  6. Ilgar

    Ilgar New Member

    Публикаций:
    0
    Регистрация:
    21 мар 2007
    Сообщения:
    9
    Да конечно, прошу прощения, Sol_Ksacap не сомненно прав, ему также моя благодарность. По поводу "L MACRO" - не знаю почему, но я очень не люблю макросы (кроме invoke&coinvoke :)) и высокоуровневые инструкции (типа .if .else и т.п.), и никогда их не использую, возможно это извращение, но мне нравиться. Еще раз большое спасибо всем кто ответил, а для тех кто столкнется с данной проблемой в будующем рабочий исходник:

    .386
    .model flat,stdcall
    option casemap:none

    include windows.inc
    include kernel32.inc
    include oaidl.inc ;(исправить структуру DISPPARAMS см. пост MirrorBlack)
    include ole32.inc
    include oleaut32.inc
    includelib kernel32.lib
    includelib ole32.lib
    includelib oleaut32.lib

    main proto

    .data
    clsid CLSID <>
    IID_NULL GUID <0,0,0,<0,0,0,0,0,0,0,0>>
    IID_IDispatch GUID <000020400H,00000H,00000H,<0C0H,000H,000H,000H,000H,000H,000H,046H>>
    szExcelApp db "Excel.Application",0
    dispID DISPID 0
    pXlApp dd 0
    mtdVisible db "Visible",0
    parm VARIANTARG <>
    dsppar DISPPARAMS <0,0,0,0>
    dispidNamed DISPID DISPID_PROPERTYPUT

    .data?
    wbuffer db 512 dup(?)
    pwbuffer dd ?

    .const

    .code

    start:
    invoke main
    invoke ExitProcess,eax

    main proc

    invoke MultiByteToWideChar,CP_ACP,0,addr szExcelApp,-1,addr wbuffer,510
    invoke CLSIDFromProgID,addr wbuffer,addr clsid
    test eax,eax
    jne @UNINITCOM

    invoke CoInitialize,0
    test eax,eax
    js @RETURN

    invoke CoCreateInstance,addr clsid,NULL,CLSCTX_LOCAL_SERVER,addr IID_IDispatch,addr pXlApp
    test eax,eax
    jne @UNINITCOM

    mov parm.vt,VT_BOOL
    mov parm.boolVal,1

    mov dsppar.cArgs,1
    lea eax,parm
    mov dsppar.rgvarg,eax
    mov dsppar.cNamedArgs,1
    lea eax,dispidNamed
    mov dsppar.rgdispidNamedArgs,eax

    invoke MultiByteToWideChar,CP_ACP,0,addr mtdVisible,-1,addr wbuffer,510
    lea eax,wbuffer
    mov pwbuffer,eax
    coinvoke pXlApp,IDispatch,GetIDsOfNames,addr IID_NULL,addr pwbuffer,1,LOCALE_USER_DEFAULT,addr dispID
    coinvoke pXlApp,IDispatch,Invoke,dispID,addr IID_NULL,800h,DISPATCH_PROPERTYPUT,addr dsppar,NULL,NULL,NULL

    @UNINITCOM:
    invoke CoUninitialize

    @RETURN:
    xor eax,eax
    ret

    main endp

    end start

    Тока не забудте перед "invoke CoUninitialize" хотя бы MessageBox вызвать, иначе вы ничего не заметите :)
     
  7. Valentin

    Valentin Member

    Публикаций:
    0
    Регистрация:
    2 ноя 2007
    Сообщения:
    128
    Подскажите: а как теперь реализовать Workbooks.Add или Rows("2:2").Select или Range("A1").Select??
    Как на АСМе сделать с excel все что захочу?
     
  8. oleg_nalad4ik

    oleg_nalad4ik Oleg

    Публикаций:
    0
    Регистрация:
    19 сен 2007
    Сообщения:
    13
    Адрес:
    Набережные Челны
    Тоже очень интересуюсь как на ASMе работать с Excel и Word.
    Ilgar может поделитесь информацией.
     
  9. Y_Mur

    Y_Mur Active Member

    Публикаций:
    0
    Регистрация:
    6 сен 2006
    Сообщения:
    2.494
    http://www.wasm.ru/article.php?article=comkit1
     
  10. Ilgar

    Ilgar New Member

    Публикаций:
    0
    Регистрация:
    21 мар 2007
    Сообщения:
    9
    Поделюсь, т.к. сам очень долго искал подобную информацию, мало кто отвечает конкретно, приходится вытягивать каждое движение, но я понимаю, лень, я и сам такой, пока мне не лень отвечать - вот исходник, компилится в WinAsm Studio, можно и в masm.

    Делает следующее:
    1. Запускает MS Excel
    2. Делает его видимым
    3. Выделяет диапазон "A1:B1"
    4. Рисует границы
    5. Окрашивает диапазон в желтый цвет
    6. Выравнивает по центру (горизонталь, вертикаль)
    7. Работает с Safe Array (это хорошая штука, если нужно вставить много данных во много ячеек и сразу)
    8. Вид -> разметка страницы
    9. Масштаб 128%
    10. Перенос по словам
    11. Авто фильтр
    12. Пишем нехорошие слова, шрифтом "Time New Roman/красный/жирный/косой/подчеркнутый"
    12. Сохраняем как "D:\test.xls" (как это сделать мне вообще никто не смог ответить, даже на C++ - на этом форуме не спрашивал, здесь, если не лень, всему научат :))
    13. Выходим

    Все телодвижения делаются с помощью плагиатированной функции MS AutoWrap, реализация возможно не совершенна, но рабочая. С ее помощью можно делать все, что захотите, в рамках того что может сам Excel/Word.
    Как сделать то, чего нет в исходнике?
    Ответ: Запускаем Excel->Сервис->Макрос->Начать запись->Делаем все что нужно->Смотрим что получилось->Используя MS AutoWrap делаем то же самое.
    Как это сделать с MS Word? Ответ: также как и с MS Excel :) Ну вот мне уже и стало лень. Надеюсь это кому нибуль пригодиться :)
     
  11. Valentin

    Valentin Member

    Публикаций:
    0
    Регистрация:
    2 ноя 2007
    Сообщения:
    128
    Ilgar, большое спасибо!!
     
  12. Valentin

    Valentin Member

    Публикаций:
    0
    Регистрация:
    2 ноя 2007
    Сообщения:
    128
    Ilgar, а Вы не пробовали реализовать доступ к COM Excel и не запуская Excel выполнять все операции в своем окне своей программы?
     
  13. al79

    al79 Алексей

    Публикаций:
    0
    Регистрация:
    11 май 2006
    Сообщения:
    133
    Адрес:
    Екатеринбург
    А подскажет кто нибудь, как открыть xls файл.
    Делал вот так
    Добавил в программу Ilgar, вот это:
    Код (Text):
    1. mtdOpen           db          "Open",0
    2.  
    3. xlsOpen proc
    4.    
    5.     LOCAL   l_parm:VARIANT
    6.     LOCAL   l_result:VARIANT
    7.     LOCAL   bstr_in:BSTR
    8.    
    9.    
    10.     mov     l_parm.vt,VT_I4
    11.     mov     l_parm.lVal,1
    12.    
    13.     invoke  AutoWrap,DISPATCH_PROPERTYGET,addr l_result,pXlApp,addr mtdWorkBooks,1,addr l_parm
    14.     mov     eax,l_result.pdispVal
    15.     mov     pXlWorkBooks,eax
    16.    
    17.     invoke  MultiByteToWideChar,CP_ACP,0,addr szSaveAs,-1,addr wbuffer,510
    18.    
    19.     mov     l_parm.vt,VT_BSTR
    20.     invoke  SysAllocString,addr wbuffer
    21.     mov     bstr_in,eax
    22.     mov     l_parm.bstrVal,eax
    23.    
    24.     invoke  AutoWrap,DISPATCH_METHOD,0,pXlWorkBooks,addr mtdOpen,1,addr l_parm
    25.    
    26.     invoke  SysFreeString,bstr_in
    27.    
    28.     ret
    29. xlsOpen EndP
    Заменил call xlsAddBook на call xlsOpen
    Но что то не хочет открываться, только пустая форма EXCEL и все.