AXForum  
Вернуться   AXForum > Microsoft Dynamics AX > DAX: Программирование
All
Забыли пароль?
Зарегистрироваться Правила Справка Пользователи Сообщения за день Поиск Все разделы прочитаны

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 31.01.2007, 16:54   #1  
Romsrs is offline
Romsrs
Участник
 
4 / 10 (1) +
Регистрация: 14.07.2006
? Проблема с импортом из Excel через COM
Здравствуйте!

Проблема такая: импортируются данные из excel-файла через COM:
excelApplication = new COM(#EXCEL);
...
и т.д.

Импорт проходит успешно. Но, если в процессе импорта открыть ЛЮБОЙ файл excel, содержащий макросы, и появится предупреждение системы безопасности, то возникает ошибка при обращении к методам COM-объекта.
Например:

if (excelApplication)
{
excelApplication.quit();
excelApplication.finalize();
}

Ошибка: COM-объект не имеет метода quit.

При этом excelApplication в отладчике уже не _Application, но и не null, а EXCEL остается в памяти.

Не подскажите как с этим бороться?
Старый 31.01.2007, 20:45   #3  
fomenka is offline
fomenka
Участник
 
97 / 14 (1) ++
Регистрация: 25.02.2003
По-моему, человек спрашивал про другой случай. У него проблема с контекстом безопасности. Код ошибки не сообщите?

Самое простое, но не самое лучшее, - смените уровень безопасности. Хотя, если вы сторонними файлами Excel не пользуетесь, то почему нет?
Можно подписывать свои проекты, как советует Microsoft. На подписанные макросы ругаться при открытии не будет.
Старый 31.01.2007, 20:55   #4  
olesh is offline
olesh
Участник
 
58 / 26 (1) +++
Регистрация: 02.04.2002
Адрес: Москва
Цитата:
Сообщение от fomenka Посмотреть сообщение
По-моему, человек спрашивал про другой случай. У него проблема с контекстом безопасности.
Да, Romsrs спрашивал про другое. Проблема более общая. Диалог про безопасность - это частный случай. Другой вариант - когда юзер открывает файл, который кем-то другим редактируется (диалог, типа, "Открыть файл для чтения, сообщить когда освободится..."). Тоже импорт отваливается.

Конечно, есть простое решение - рекомендация пользователю не трогать Excel во время импорта
Старый 31.01.2007, 23:14   #5  
AndyD is offline
AndyD
Участник
КОРУС Консалтинг
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
 
2,560 / 2479 (88) +++++++++
Регистрация: 20.08.2005
По поводу ошибки с макросами - перед открытием файла сделайте вызов excelApplication .AutomationSecurity(1) (1 - открывать с включенными макросами без запроса; 2 - открывать в зависимости от параметров безопасности; 3 - открывать с отключенными макросами без запроса)

2 olesh
Запрос на открытие файла в режиме реадонли регулируется параметром Notify метода Open() коллекции Workbooks. Если его значение TRUE, то файл открывается без запроса
__________________
Axapta v.3.0 sp5 kr2
Старый 01.02.2007, 08:26   #6  
olesh is offline
olesh
Участник
 
58 / 26 (1) +++
Регистрация: 02.04.2002
Адрес: Москва
2 AndyD
Еще раз повторю - проблема не при открытии файла в Аксапте!

Т.е. делаем так - запускаем некий импорт в Аксапте из файла 1.xls, импорт идет, занимает какое-то время. В это время юзер решает открыть файл 2.xls в екселе обычным способом.
При этом, если в нем есть макросы или файл редактируется другим пользователем, то ексель показывает соответствующий диалог. Тут же импорт в Аксапте вываливается с ошибкой "нет метода у объекта" (варианты - нет quit у excelApplication или value у range). При этом ошибка с отсутствием метода value сразу приводит к вываливанию стека в infolog, в catch она не ловится, в результате процесс excel.exe остается в памяти.

Аналогично себя ведет и стандартный импорт из ексельных файлов в Аксапту (который Администрирование / Пер. опер. / Экспорт/Импорт).

Последний раз редактировалось olesh; 01.02.2007 в 08:28.
Старый 01.02.2007, 10:18   #7  
gl00mie is offline
gl00mie
Участник
MCBMSS
Most Valuable Professional
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
3,684 / 5798 (201) ++++++++++
Регистрация: 28.11.2005
Адрес: Москва
Записей в блоге: 3
Цитата:
Сообщение от olesh Посмотреть сообщение
Да, Romsrs спрашивал про другое. Проблема более общая.
Цитата:
Сообщение от olesh Посмотреть сообщение
Еще раз повторю - проблема не при открытии файла в Аксапте!
Вот так и выявляются на форуме люди, работающие вместе
Цитата:
ошибка с отсутствием метода value сразу приводит к вываливанию стека в infolog, в catch она не ловится, в результате процесс excel.exe остается в памяти.
Аналогично себя ведет и стандартный импорт из ексельных файлов в Аксапту (который Администрирование / Пер. опер. / Экспорт/Импорт).
А вариант импорта данных из Excel без использования его COM-объектов вы не рассматривали?..
Старый 01.02.2007, 10:31   #8  
olesh is offline
olesh
Участник
 
58 / 26 (1) +++
Регистрация: 02.04.2002
Адрес: Москва
Цитата:
Сообщение от gl00mie Посмотреть сообщение
А вариант импорта данных из Excel без использования его COM-объектов вы не рассматривали?..
Рассматривали. На данный момент больше всего нравится импорт через массивы с помощью COM. ADO не понравилось.

Но вопрос не в этом
Старый 01.02.2007, 10:37   #9  
belugin is offline
belugin
Участник
Аватар для belugin
Сотрудники Microsoft Dynamics
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии 2011
Лучший по профессии 2009
 
4,622 / 2925 (107) +++++++++
Регистрация: 16.01.2004
Записей в блоге: 5
А мне больше всего нравится импорт через tsv
Старый 01.02.2007, 10:39   #10  
gl00mie is offline
gl00mie
Участник
MCBMSS
Most Valuable Professional
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
3,684 / 5798 (201) ++++++++++
Регистрация: 28.11.2005
Адрес: Москва
Записей в блоге: 3
Цитата:
Сообщение от olesh Посмотреть сообщение
Рассматривали. На данный момент больше всего нравится импорт через массивы с помощью COM. ADO не понравилось.
Как вариант можно попробовать пересохранять файл Excel в XML-формате (думаю, это тоже можно автоматизировать, и происходить это будет быстрее, чем импорт), а потом уже работать с этим XML без привлечения Excel'я...
Старый 01.02.2007, 10:39   #11  
gl00mie is offline
gl00mie
Участник
MCBMSS
Most Valuable Professional
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
3,684 / 5798 (201) ++++++++++
Регистрация: 28.11.2005
Адрес: Москва
Записей в блоге: 3
Цитата:
Сообщение от belugin Посмотреть сообщение
А мне больше всего нравится импорт через tsv
А кто это?.. В смысле csv?

Последний раз редактировалось gl00mie; 01.02.2007 в 10:42.
Старый 01.02.2007, 11:02   #12  
belugin is offline
belugin
Участник
Аватар для belugin
Сотрудники Microsoft Dynamics
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии 2011
Лучший по профессии 2009
 
4,622 / 2925 (107) +++++++++
Регистрация: 16.01.2004
Записей в блоге: 5
Tab separated value
Старый 01.02.2007, 17:12   #13  
AndyD is offline
AndyD
Участник
КОРУС Консалтинг
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
 
2,560 / 2479 (88) +++++++++
Регистрация: 20.08.2005
2 olesh

Проблема в том, что новый файл открывается в том же процессе, где идет обработка. В результате, при появлении окна с пользовательским запросом, блокируются обращения через COM-интерфейсы. Как только окно закрывается обработка может быть продолжена.

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

В общем что надо сделать:
Открыть regedit.exe. Найти ветку "HKEY_CLASSES_ROOT\Excel.Sheet.*\shell\Open" (вместо звездочки - номер версии. У меня Excel 2003 и стоит 8. В общем, найти с таким номером, что бы была подветка shell). В ветке Open будут две подветки: Command и ddeexec. ddeexec надо будет удалить. В ветке Command изменить значение строкового ключа command (у меня ?r=^Vn-}f(ZXfeAR6.jiEXCELFiles>!De@]Vz(r=f`1lfq`?R& /e) - в конце после /e приписать " %1". Если ключа command не будет - добавьте " %1" в значение по умолчанию

После этого файлы должны открываться в раздельных процессах.
Перед изменениями экспортируйте эту ветку, что бы восстановить значения в случае проблем.
__________________
Axapta v.3.0 sp5 kr2
За это сообщение автора поблагодарили: olesh (1).
Старый 01.02.2007, 18:46   #14  
olesh is offline
olesh
Участник
 
58 / 26 (1) +++
Регистрация: 02.04.2002
Адрес: Москва
Цитата:
Сообщение от AndyD Посмотреть сообщение
Проблема в том, что новый файл открывается в том же процессе, где идет обработка. В результате, при появлении окна с пользовательским запросом, блокируются обращения через COM-интерфейсы. Как только окно закрывается обработка может быть продолжена.
А нельзя каким-либо образом поймать эту ситуацию внутри Аксапты?

Править реестр у сотни юзеров, конечно, не вариант.
Старый 01.02.2007, 22:56   #15  
AndyD is offline
AndyD
Участник
КОРУС Консалтинг
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
 
2,560 / 2479 (88) +++++++++
Регистрация: 20.08.2005
Можно сделать так.
X++:
class ExcelFuncs
{
}

static client ComVariant GetValue(Com Range)
{
    ComDispFunction func = new ComDispFunction(range, "Value", ComDispContext::PropertyGet);
    ComVariant var = new ComVariant(ComVariantInOut::Out_retVal, ComVariantType::VT_ERROR);
    int line;
    int i;
    str s;
    ;
    SetPrefix("CallWasRejectedByCallee");
    while (true)
        try
        {
            line = infolog.line();
            func.call(var);
            return var;
        }
        catch
        {
            if (infolog.line() > line)
            {
                s = infolog.text(line+1);
                if (strscan(s, "Value", 1, strlen(s)))
                {
                    s = substr(s, strscan(s, "0x", 1, strlen(s))+2, 8);
                    if (s == "80010001")
                    {
                        sleep(100);
                        infolog.cut(line+1);
                        continue;
                    }
                }
            }
            throw Exception::Error;
        }
    throw error("Ошибка при получении значения!");
}
Пример вызова.
X++:
static void Sample(Args _args)
{
    ComExcelDocument_Ru excel = new ComExcelDocument_Ru();
    Com doc;
    Com app;
    Com Sheet;
    Com Range;
    ComVariant var;
    ;
    excel.open("c:\\Temp\\TestExcel.xls", true);
    doc = excel.getComDocument();
    app = doc.Application();
    sheet = app.ActiveSheet();
    range = sheet.range("A1:J1");
    info("aaa");
    while (true)
    {
//        info("bbb");
        var = ExcelFuncs::GetValue(range);
    }
}
Для проверки можно запустить джоб и внести что-либо в ячейку. Пока будет происходить пользовательский ввод - код ожидает его кончания (аналогично с диалоговыми окнами). По окнчанию ввода (закрытию диалогового окна) обработка продолжится.
Если закрыть окно Excel, то произойдет окончание работы job'а по exception'у.

Хотя, мне это решение не нравится.
Во-первых, нет возможности явно определить код возврата из вызова функции (при получении значения, не равного S_OK, ядро генерирует exception). Например, если раскомментарить строку info("bbb"), то в инфолог будет выводиться форматная строка без передачи параметров (вместо имени функции и кода ошибки будут %1, %2 и т.д.) (проверял на SP3 и SP5 без роллапов)
Во-вторых, ожидание пока пользователь как-то отреагирует на появившиеся диалоги (возможность ввода данных в ячейки оставлена для примера). Напомню, что пока будут выведены эти окна, интерфейсы не будут работать (будет возвращаться ошибка 0x80010001, либо не будут находиться какие-то методы).

Еще есть такой вариант - написать Comобъект-обертку над методами Excel'я с возможностью получения кода возврата из экселевских методов. Тогда пропадет неоднозначность, правда, второй пункт и в этом случае останется в силе.
__________________
Axapta v.3.0 sp5 kr2
За это сообщение автора поблагодарили: kvg6 (1).
Старый 02.02.2007, 11:02   #16  
gl00mie is offline
gl00mie
Участник
MCBMSS
Most Valuable Professional
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
3,684 / 5798 (201) ++++++++++
Регистрация: 28.11.2005
Адрес: Москва
Записей в блоге: 3
Цитата:
Сообщение от AndyD Посмотреть сообщение
Проблема в том, что новый файл открывается в том же процессе, где идет обработка. В принципе, можно настроить таким образом, что бы экселевские файлы открывались в отдельных процессах. Минусы - если пользователь откроет файл и затем снова это сделает (из проводника), то переключения на уже открытый не произойдет и появится окошко с сообщением об открытии только для чтения и т.д.
Еще один минус: копирование/перемещение листов между книгами Excel работает только тогда, когда они открыты в одном процессе. Соотв., для перемещения/копирования листов придется открывать второй и последующие файлы Excel уже не из проводника, а из самого Excel'я, что бывает очень неудобно.

Последний раз редактировалось gl00mie; 02.02.2007 в 11:04.
Старый 02.02.2007, 11:32   #17  
AndyD is offline
AndyD
Участник
КОРУС Консалтинг
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
 
2,560 / 2479 (88) +++++++++
Регистрация: 20.08.2005
Еще один способ - отключение реагирования на DDE запросы в процессе-обработчике. Перед закрытием Excel параметр восстановить обратно (В обязательном порядке!!! Иначе открыть файл из проводника не получится).
X++:
static void ExcelImportTest(Args _args)
{
    ComExcelDocument_Ru excel = new ComExcelDocument_Ru();
    com doc;
    com app;
    com sheet;
    com range;
    ComVariant var;
    boolean ignore;
    ;
    excel.open("c:\\Temp\\Test.xls", false);

    doc = excel.getComDocument();
    app = doc.application();
    ignore = app.IgnoreRemoteRequests();
    app.IgnoreRemoteRequests(true);

    try
    {
        sheet = app.activesheet();
        range = sheet.range("A1:J1");
        while (true)
            var = range.value();
    }
    catch
    {
        info("catch"); // из обработки вываливаемся по брейку
    }
    app.IgnoreRemoteRequests(ignore);
    app.quit();
}
Минусы - нельзя будет организовать обмен с Excel через DDE.
__________________
Axapta v.3.0 sp5 kr2
За это сообщение автора поблагодарили: fomenka (1), gl00mie (3), Romsrs (1).
Старый 02.02.2007, 12:01   #18  
Romsrs is offline
Romsrs
Участник
 
4 / 10 (1) +
Регистрация: 14.07.2006
Всем большое спасибо!

2 AndyD
Отдельное спасибо! Последний способ помог!
Старый 10.06.2008, 10:34   #19  
Dronas is offline
Dronas
Участник
 
213 / 14 (1) ++
Регистрация: 16.11.2004
Цитата:
Сообщение от AndyD Посмотреть сообщение
Еще один способ - отключение реагирования на DDE запросы в процессе-обработчике. Перед закрытием Excel параметр восстановить обратно (В обязательном порядке!!! Иначе открыть файл из проводника не получится).
X++:
static void ExcelImportTest(Args _args)
{
    ComExcelDocument_Ru excel = new ComExcelDocument_Ru();
    com doc;
    com app;
    com sheet;
    com range;
    ComVariant var;
    boolean ignore;
    ;
    excel.open("c:\\Temp\\Test.xls", false);

    doc = excel.getComDocument();
    app = doc.application();
    ignore = app.IgnoreRemoteRequests();
    app.IgnoreRemoteRequests(true);

    try
    {
        sheet = app.activesheet();
        range = sheet.range("A1:J1");
        while (true)
            var = range.value();
    }
    catch
    {
        info("catch"); // из обработки вываливаемся по брейку
    }
    app.IgnoreRemoteRequests(ignore);
    app.quit();
}
Минусы - нельзя будет организовать обмен с Excel через DDE.
После этого кода excel перестал открывать файлы, кликаешь на файл, открывается excel, файл можно после этого открыть только через меню Может кто в курсе ка полечить?
Теги
com connector, excel, импорт, com-объект

 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
работа 1С из Аксапты через COM _scorp_ DAX: Программирование 7 22.08.2008 15:45
Работа с Excel через COM в DAX 4.0 Paul_ST DAX: Программирование 4 17.07.2007 16:45
Excel COM в тонком и толстом клиенте Goldy DAX: Программирование 10 07.07.2006 21:40
связь с 1С через COM rinugun DAX: Программирование 9 03.12.2004 11:28
Экспорт в Excel через WorkBooks.OpenText() Владимир Максимов DAX: Программирование 2 09.04.2004 17:16
Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход

Рейтинг@Mail.ru
Часовой пояс GMT +3, время: 20:24.