09.07.2010, 16:43 | #1 |
Участник
|
Ошибка времени выполнения в ComExcelDocument_RU.findRange()
DAX 2009 и Excel 2007.
При вызове метода insertRows класса ComExcelDocument_RU, по непонятным мне причинам, на одних и тех же данных время от времени вываливается ошибка времени выполнения "неправильные типы аргументов в операции присвоения значения переменной" на 18 строке метода findRange X++: comApplication = m_comDocument.application(); метод insertRows X++: void insertRows(int _fromRow, int _toRow, int _fromWorkSheet = 1, int _offset = 1, int _numOfCopies = 1, // CIT_MSOfficeReport, kirp --> /* int _toWorkSheet = 1) */ int _toWorkSheet = 1, MSOfficeBookMark_RU _copyFromBookmark = "") // CIT_MSOfficeReport, kirp <-- { COM comRows, comWorkSheet, comRow, comRowTarget, selection; COMVariant comRowVariant, selVariant; ; if (_numOfCopies <= 0) return; if (! m_comDocument) throw error(strfmt("@GEE6401", this.getApplicationName())); // CIT_MSOfficeReport, kirp --> if (_copyFromBookmark) { comRow = this.findRange(_copyFromBookmark, _fromWorkSheet); comRow.copy(); } else { // CIT_MSOfficeReport, kirp <-- comRow = this.findRange(strFmt("%1:%2", _fromRow, _toRow), _fromWorkSheet); comRow.copy(); // CIT_MSOfficeReport, kirp --> } // CIT_MSOfficeReport, kirp <-- comRowTarget = this.findRange(strFmt("%1:%2", _fromRow + _offset, _fromRow + _offset + (_toRow - _fromRow + 1) * _numOfCopies - 1), _toWorkSheet); comRowTarget.select(); comRowTarget.insert(); comWorkSheet = this.getWorkSheet(_toWorkSheet); comRows = comWorkSheet.cells(); comRows = COM::createFromVariant(comRows.item(1)); comRows.select(); m_comApplication.cutCopyMode(false); } X++: // Creates object range type named the same way as Excel bookmark // bookMark -> Excel bookmark name // CIT_MSOfficeReport, ilso --> /* protected COM findRange(MSOfficeBookMark_RU bookMark, int _workSheet = 1) */ public COM findRange(MSOfficeBookMark_RU bookMark, int _workSheet = 1) // CIT_MSOfficeReport, ilso <-- { COM comRange, comWorkSheet; COM comApplication; ; if (m_comDocument) { comWorkSheet = this.getWorkSheet(_workSheet); comApplication = m_comDocument.application(); comWorkSheet.activate(); if (comWorkSheet && comApplication) { comRange = comApplication.range(bookMark); } } return comRange; } Подскажите, пожалуйста, в чем может быть дело. PS. В поиске ничего не нашел. |
|
09.07.2010, 17:30 | #2 |
Microsoft Dynamics
|
В таймаутах. В РУ4 или РУ5 были добавлены пара макросов StartSafeCall_RU и EndSafeCall_RU. Пример их использования можно посмотреть в методах класса LedgerRRGRunReport_RU. Например, в addWorksheets(...), outputValue(...) и removeWorksheets(...).
Это должно Вам помочь. |
|
|
За это сообщение автора поблагодарили: alexbn (1), Logger (4), Daiver (1), AlexArh (1), alex55 (1), Андрей К. (1). |
12.07.2010, 18:16 | #3 |
Участник
|
Спасибо, буду разбираться.
|
|
13.01.2011, 20:45 | #4 |
Участник
|
А может кто-нить разъяснить, что за таймауты такие появились, где про них написано, и в чем суть макроса EndSafeCall_RU? Я так понимаю, он просто при возникновении ошибки пытается повторно вызвать обрамленный макросами код указанное число раз, делая небольшие паузы между повторами. Зачем для этого используется такая конструкция?
X++: #define.safeCallTimeOut(250) #define.safeCallNotifyMethod('notify') infolog.addTimeOut(infolog, #safeCallNotifyMethod, #safeCallTimeOut); infolog.wait(); retry; |
|
13.01.2011, 22:29 | #5 |
Участник
|
Это из той же оперы ? Ошибка чтения файлов XLS под Windows 7
Но это в АХ.4sp2. Так и не победили пока. |
|
13.01.2011, 23:23 | #6 |
Участник
|
А фиг знает, может, и из той же. Сейчас вот вылечился экспорт данных в Excel через ComExcelDocument_RU, который, зараза, валился буквально от любого чиха: мышкой не туда ткнешь - и привет. Вылечилось обрамлением шаманскими макросами вызовов методов COM-объектов в методах findRange, getWorkSheet, insertValueInRange.
|
|
13.01.2011, 23:57 | #7 |
Microsoft Dynamics
|
Я этот прием подсмотрел в функции выгрузки данных таблицы в ексель. Немного причесал для своих целей и оформил для удобства ввиде пары макросов.
Почему не sleep? Не помню. Может, потому что sleep замораживал бы систему. А может, по какой-то другой причине. |
|
14.01.2011, 12:00 | #8 |
Участник
|
Видимо не такой уж он был и safe, этот timeout
|
|
14.01.2011, 13:09 | #9 |
Участник
|
Да тут не до смеха.
Нам тут рекламируют везде, что в каждой следующей версии улучшается интеграция DAX со всем чем можно на свете, а с офисом и подавно. Но что-то не очень на это похоже. По крайней мере в 3-ке таких проблем не было, либо они было крайне редкими. Неужели уж такие баги нельзя закрыть ? |
|
14.01.2011, 13:19 | #10 |
Microsoft Dynamics
|
Цитата:
У вас какой офис был, когда вы в трешке работали? Попробуйте с ним же поработать в 2009-ой. По поводу багов, что вы имеете ввиду? |
|
14.01.2011, 13:22 | #11 |
Участник
|
Если бы в новых офисах !
У нас используются терминальные сервера, на которых стоит 2003-й офис и при переходе на с трешки на 2009-ю Аксапту мы их не меняли. Просто доустановили клиента DAX 2009 на терминальные сервера и все. |
|
14.01.2011, 13:24 | #12 |
Участник
|
|
|
14.01.2011, 17:00 | #13 |
Microsoft Dynamics
|
Ну, не в офисе, так не в офисе. У меня сложилось такое мнение, поскольку новые проблемы приходили после установки нового офиса.
По поводу, чем должно заниматься ядро, чем нет. Я не думаю, что именно ядро ответственно за то, каким образом вы решаете свои функциональные задачи. Не нравится как работает COM, пользуйтесь XML, буфером обмена или другими вариантами. Кстати, я сам не проверял, но если вызывать офисные COM объекты из какой-нибудь другой среды,скажем из программы на .net, то там все проходит гладко? Без необходимости использования таймаутов? Или те же самые грабли? |
|
14.01.2011, 17:17 | #14 |
Участник
|
Про другие системы я тоже не проверял.
Если 3-ку считать другой системой - то в ней работало. Вам кстати отдельное спасибо за Ошибка времени выполнения в ComExcelDocument_RU.findRange() сами мы еще долго могли бы ковыряться в поисках решения проблемы. |
|
17.01.2011, 13:54 | #15 |
Участник
|
Таймауты и повтор кода - это не решение проблемы. Это временная "затычка", чтобы "отвязались". Но рано или поздно это все равно "выйдет боком". Т.е. возникнет ситуация когда даже многократный повтор ничем не поможет. Я с этим уже много раз и в разных ситуациях сталкивался.
Как мне кажется, в данном случае, проблема носит общий характер. Здесь "виноваты" все 3 участника: Windows, Excel и Axapta. В разной степени и по разным причинам, но именно все вместе. Со стороны ядра Axapta - явно не вполне корректная работа с COM-объектами. Начиная с конвертации переменных и кончая работой с "многочленами". Все время приходится "пальцем придерживать" Со стороны Excel - какая-то проблема с загрузкой COM-интерфейса. Иногда как следствие каких-либо системных сообщений, которые при работе через Com-интерфейс не видны, но сам факт их появления блокирует дальнейшую работу Ну, а собственно Windows, вероятно, может являться причиной проблем загрузки COM-интерфейса. Разумеется, это лишь мое предположение. |
|
28.02.2011, 14:04 | #16 |
Участник
|
Тоже столкнулись с этой проблемой, идея сделать как в российском функционале, с макросами на try catch очень не понравилась, да и объем переписывания немалый
Проблема возникала только на системах с Win7, XP + Office 2010 + dax 2009 работало без проблем Когда искал причину, увидел что в других языках обращения к COM компилируются с атрибутом [STAThread] - однопоточное исполнение, ну и появилась мысль что многопоточность Win7 мешает жить. Попытка запустить dax2009 в режиме совместимости чуть улучшила ситуацию, но проблему не решила и тогда пришла идея запустить класс экспорта в отдельном потоке, и все заработало Сейчас все протестировано в разных связках, в том числе и в 64-битной системе, все работает, и переписывать нужно только способ запуска класса |
|
|
За это сообщение автора поблагодарили: Logger (5), Ace of Database (2), coolibin (1), vc (1), alex55 (1), someOne (1). |
02.03.2011, 11:41 | #17 |
Участник
|
Цитата:
Сообщение от gl00mie
Сейчас вот вылечился экспорт данных в Excel через ComExcelDocument_RU, который, зараза, валился буквально от любого чиха: мышкой не туда ткнешь - и привет. Вылечилось обрамлением шаманскими макросами вызовов методов COM-объектов в методах findRange, getWorkSheet, insertValueInRange.
|
|
02.03.2011, 12:58 | #18 |
Участник
|
Цитата:
Вот код макроса EndSafeCall_RU : X++: // %1 retry count by default 4 // %2 time out by default 250 // %3 exception type by default Exception::Error #ifnot.empty(%1) #define.safeCallRetryCount(%1) #endif #if.empty(%1) #define.safeCallRetryCount(4) #endif #ifnot.empty(%2) #define.safeCallTimeOut(%2) #endif #if.empty(%2) #define.safeCallTimeOut(250) #endif #ifnot.empty(%3) #define.safeCallExceptionType(%3) #endif #if.empty(%3) #define.safeCallExceptionType(Exception::Error) #endif catch (#safeCallExceptionType) { if (xSession::currentRetryCount() >= #safeCallRetryCount) { throw #safeCallExceptionType; } else { #define.safeCallNotifyMethod('notify') infolog.clear(0); infolog.addTimeOut(infolog, #safeCallNotifyMethod, #safeCallTimeOut); infolog.wait(); retry; } } X++: try Может лучше копать в сторону "однопоточного" запуска, предложенного AndreyStar ? Кто знает как это делать ? Через thread ? Но это ведь тоже определенное извращение... |
|
|
За это сообщение автора поблагодарили: S.Kuskov (1). |
02.03.2011, 13:29 | #19 |
Участник
|
Цитата:
Сообщение от AndreyStar
Когда искал причину, увидел что в других языках обращения к COM компилируются с атрибутом [STAThread] - однопоточное исполнение, ну и появилась мысль что многопоточность Win7 мешает жить. Попытка запустить dax2009 в режиме совместимости чуть улучшила ситуацию, но проблему не решила и тогда пришла идея запустить класс экспорта в отдельном потоке, и все заработало
Сейчас все протестировано в разных связках, в том числе и в 64-битной системе, все работает, и переписывать нужно только способ запуска класса |
|
02.03.2011, 14:12 | #20 |
Участник
|
Цитата:
Сообщение от AndreyStar
Тоже столкнулись с этой проблемой, идея сделать как в российском функционале, с макросами на try catch очень не понравилась, да и объем переписывания немалый
Проблема возникала только на системах с Win7, XP + Office 2010 + dax 2009 работало без проблем Когда искал причину, увидел что в других языках обращения к COM компилируются с атрибутом [STAThread] - однопоточное исполнение, ну и появилась мысль что многопоточность Win7 мешает жить. Попытка запустить dax2009 в режиме совместимости чуть улучшила ситуацию, но проблему не решила и тогда пришла идея запустить класс экспорта в отдельном потоке, и все заработало Сейчас все протестировано в разных связках, в том числе и в 64-битной системе, все работает, и переписывать нужно только способ запуска класса Запускаем импорт из екселя, например, так X++: thread thread = new thread(); thread.setInputParm(["Т000081968", "c:\text.xlsx"]); // какие то параметры thread.run(classnum(TetImportClass), identifierstr(importFromExcel)); X++: static client void importFromExcel(thread _thread) ComExcelDocument_RU document = new ComExcelDocument_RU(); str path; str parm; ; [parm, path] = _thread.getInputParm(); document.open(path, false); ..... .... Какое никакое, но все же решение. Только теперь ряд других проблем имеется, например перехват ошибок и вывод их на экран - не тривиальная задача. Но решаемая. |
|
|
За это сообщение автора поблагодарили: Logger (3), Ace of Database (5). |
Теги |
com-объект, excel, thread, асинхронный com, ошибка |
|
|