01.06.2011, 12:46 | #1 |
Axapta
|
DDE в Ax2009
Когда-то очень давно я уже поднимал вопрос о работе с DDE в Аксапте. Если в 3.0 все работало на ура, то в 4.0 заставить нормально работать так и не получилось (подробностей за давностью лет уже не помню). Настала пора версии 2009.
Вроде в данной версии все должно работать. Однако цветочек каменный что-то пока не выходит, да и слово "счастье" из известных четырех букв тоже не складывается. 1. Имеется следующий простой джоб: X++: static void DDETest1(Args _args) { DDEClient DDEClient; ; dDEClient = new DDEClient( 'excel', 'system' ); info(DDEClient.request('SysItems')); } 2. В случае, если первый тест пройден успешно, создайте в С:\Temp шаблон DDETest.xlt и запустите следующий вырванный из контекста джоб (в 3.0 работает без проблем): X++: static void DDETest2(Args _args) { ComExcelDocument_RU excellDocument = new ComExcelDocument_RU(); DDEClient dDEClientPar; str sDocName; Array arDDEClient; COM comDoc; void addDDEClient( str _chanelName ) { DDEClient dDEClient; str sWorkSheetName; int sheetIdx; COM workSheets; if( StrScan( _chanelName, sDocName, 1, strlen( _chanelName ) ) ) { dDEClient = new DDEClient('excel', _chanelName ); if ( !dDEClient.isValid()) { return; } workSheets = comDoc.worksheets(); for( sheetIdx = 1; sheetIdx <= workSheets.count(); sheetIdx++ ) { sWorkSheetName = excellDocument.getWorkSheetName( sheetIdx ); sWorkSheetName = substr( sWorkSheetName, 2, strlen( sWorkSheetName ) - 2 ); if( StrScan( _chanelName, sWorkSheetName, 1, strlen( _chanelName ) ) ) { arDDEClient.value( sheetIdx, dDEClient ); break; } } } } DDEClient getDDEClient( int _workSheet = 1 ) { DDEClient dDEClientExcelSystem; str channelList; str channelName; str 1 tab = num2char(9); int foundTab; int sheetIdx; int resStrScan; int resStrLen; ; if( arDDEClient.lastIndex() == 0 ) { dDEClientExcelSystem = new DDEClient( 'excel', 'system' ); if ( !dDEClientExcelSystem.isValid() ) { throw error( "Excel не запущен!" ); } comDoc = excellDocument.getComDocument(); sDocName = comDoc.name(); channelList = dDEClientExcelSystem.request('Topics'); foundTab = strScan(channelList, tab, 1, strLen(channelList)); while (foundTab) { addDDEClient( subStr(channelList, 1, foundTab - 1) ); channelList = strDel(channelList, 1, foundTab); foundTab = strScan(channelList, tab, 1, strLen(channelList)); } if (strLen(channelList) > 0) { addDDEClient( channelList ); } } return arDDEClient.value( _workSheet ); } ; arDDEClient = new Array( Types::Class ); excellDocument.newFile('C:\\Temp\\'+ 'DDETest.xlt', false); dDEClientPar = getDDEClient(1); dDEClientPar.poke('R1C1', 'Тест' ); dDEClientPar.poke('R2C1', 'Test'); excellDocument.visible(true); } |
|
01.06.2011, 14:56 | #2 |
Участник
|
Проблема в том, что функции DDEClient.poke(Item, Data) оба значения передются как UNICODE.
Но внутри идет вызов функции DdeClientTransaction(), в которой значение pData передается как UNICODE, а параметр wFmt установлен в CF_TEXT (как ANSI текст). Соответственно, Excel неправильно интерпретирует передаваемые данные. Как возможный вариант исправления, могу предложить написать dll-ку, которая будет перехватывать вызовы DdeClientTransaction и подменяеть параметр CF_TEXT на значение CF_UNICODETEXT. Что касается 2003-го офиса, то, возможно, проблема в том же самом UNICODE, но только со стороны Excel. Возможно, он так же не умеет с ним работать. Но это только гипотеза. Проверить не на чем
__________________
Axapta v.3.0 sp5 kr2 |
|
|
За это сообщение автора поблагодарили: oip (5). |
01.06.2011, 15:04 | #3 |
Axapta
|
Цитата:
Сообщение от AndyD
Проблема в том, что функции DDEClient.poke(Item, Data) оба значения передются как UNICODE.
Но внутри идет вызов функции DdeClientTransaction(), в которой значение pData передается как UNICODE, а параметр wFmt установлен в CF_TEXT (как ANSI текст). Соответственно, Excel неправильно интерпретирует передаваемые данные. К сожалению, такого писать я не умею. |
|
01.06.2011, 16:03 | #4 |
Участник
|
В свое время (еще на 4-ке) писали в саппорт MS на эту тему. Запрос долго пинали между разными инженерами. В итоге в core team ответили, что DDE - умирающая технология и в следующих версиях поддерживаться уже не будет, поэтому мы ничего чинить не будем.
Но в 2009 я смотрю все-таки оставили классы DDE. В общем мы на том проекте все переписали на обмен через буфер обмена (у нас DDE использовался для экспорта в Excel). |
|
|
За это сообщение автора поблагодарили: George Nordic (2). |
01.06.2011, 16:21 | #5 |
Axapta
|
Вот бы где-нибудь получить официальный ответ от MS о том, что "DDE - умирающая технология и в следующих (начиная с 4.0) версиях поддерживаться уже не будет", чтобы клиентам показывать. А еще лучше если это будет в документации к системе прописано.
|
|
01.06.2011, 16:26 | #6 |
Axapta
|
Кстати, на счет "умирающей технологии"... Из AX2012 классы DDE* тоже никуда не делись.
|
|
01.06.2011, 17:06 | #7 |
Участник
|
Оживим технологию
Бросить dll-ку в папку bin клиента. Перед началом работы с DDE создавать класс DLL X++: DLL AxDDEDll = new DLL("axdde.dll"); X++: AxDDEDll.finalize();
AxDDEDll= null;
__________________
Axapta v.3.0 sp5 kr2 |
|
|
За это сообщение автора поблагодарили: raz (5), lev (1), oip (26), gl00mie (15). |
01.06.2011, 17:27 | #8 |
Axapta
|
О! На первый взгляд работает (Win 2008 R2 64 bit c Excel 2010) ! Спасибо! Буду теперь это дело тестить в различных условиях. А на быстродействии сильно сказаться не может никак?
|
|
01.06.2011, 17:33 | #9 |
Участник
|
Там только вызов функции IsTextUnicode() используется, для надежности.
Сказать, на сколько она будет снижать скорость не берусь, но можно протестировать с запущенной dll-кой и без нее. Если передавать данные не поячеечно, а одним запросом, думаю, скорость будет отличаться очень мало
__________________
Axapta v.3.0 sp5 kr2 |
|
01.06.2011, 17:36 | #10 |
Axapta
|
Данные в большинстве случаев передаются поячеечно. Ок, понял. Буду тестировать. Еще раз спасибо!
|
|
01.06.2011, 18:08 | #11 |
Участник
|
А потестировать можно в тройке.
Там функция IsTextUnicode() то же будет вызываться, так что разницу в быстродействии можно будет увидеть (если она есть) А вот данные в обоих случаях (с dll и без нее) будут загружаться нормально, так что с точки зрения конечного результата будет идентично PS Погонял тест под трешкой с dll-кой и без нее - время выполнения практически одинаковое (плюс-минус пару десятков миллисекунд в обоих случаях на 20 тыс. вызовов Poke())
__________________
Axapta v.3.0 sp5 kr2 Последний раз редактировалось AndyD; 01.06.2011 в 18:21. |
|
01.06.2011, 18:52 | #12 |
Axapta
|
Ага, спасибо! Я тоже уже проверил и пока проблем не обнаружил.
Для Ax2012 тоже проверил. Без dll-ки не работает, с ней - работает. |
|
02.06.2011, 14:01 | #13 |
Axapta
|
Для работы вышеприведенной dll требуется, чтобы был установлен Microsoft Visual C++ 2010 Redistributable Package. Работоспособность проверялась на WinXP, Win2003, Win2003 R2, Win 2008 R2 (64 bit) в комбинациях с Excel 2007 и 2010.
|
|
02.06.2011, 14:07 | #14 |
Участник
|
Ага.
Либо взять вот эту dll-ку. Для нее не требуется райн-тайм лайбрари
__________________
Axapta v.3.0 sp5 kr2 |
|
|
За это сообщение автора поблагодарили: oip (5). |