AXForum  
Zurück   AXForum > Microsoft Dynamics AX > DAX: Программирование
All
Kennwort vergessen?
Registrieren Forum Rules Hilfe Benutzerliste Heutige Beiträge Suchen

 
 
Themen-Optionen Thema durchsuchen Ansicht
Alt 05.09.2011, 12:46   #1  
gl00mie ist offline
gl00mie
Участник
MCBMSS
Most Valuable Professional
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
3.684 / 5813 (201) ++++++++++
Registriert seit: 28.11.2005
Ort: Москва
Blog-Einträge: 3
Lightbulb Взаимодействие с Excel через .NET (семейство классов SysExcel)
Во вложении - проект с семейством классов SysExcel, переписанным на работу с Excel через .NET (Microsoft.Office.Interop.Excel). Модификация возникла как решение проблемы взаимодействия ядра AX 2009 с офисными приложениями через COM, что подробно описано в темах Ошибка времени выполнения в ComExcelDocument_RU.findRange() и Ошибка чтения файлов XLS под Windows 7. Через .NET экспорты/импорты стали работать намного стабильнее и субъективно чуть быстрее.
Чтобы проект скомпилировался, дополнительно нужны модификации, выложенные в темах
Вспомогательные классы проверки условий и утверждений
Класс для преобразования значений между различными значимыми типами
Также для работы модификации, разумеется, нужны установленные сборки, в которых реализованы классы и enum'ы из пространства имен Microsoft.Office.Interop.Excel. Проверялось всё на Ms Office 2010 и ядре AX 2009 SP1 RU6/RU7.

Внимание! Работу с Excel вашего или чужого кода через .NET нужно тщательно тестировать, к примеру, у меня не заработало объединение ячеек, используемое в \Classes\SysDataExcelCOM\addLookup, которое на ура отрабатывает через COM. Включается работа сеймейства SysExcel через .NET в методе SysExcel::mustInteropViaNET(). Я лично не решился пока на тотальное включение взаимодействия с Excel через .NET и сделал метод, который анализирует стек вызовов и включает работу через .NET в зависимости от того, видит ли он там "разрешенные" классы или нет. За счет этого для включения/выключения работы через .NET не пришлось как-то специально править код, работающий с классами SysExcel, хотя другого рода правки потребовались: пришлось вычистить те места, где работа шла напрямую с COM-объектами, обертками для которых служит семейство SysExcel, в результате пришлось добавить несколько новых классов-оберток.
Для удобства импорта из Excel в SysExcelRange был добавлен метод valueTyped(), возвращающий значение ячейки, приведенное к требуемому базовому аксаптовскому типу. Вся логика преобразования типов реализована в отдельном классе. Также в SysExcelApplication был добавлен метод findRange(), позволяющий найти SysExcelRange из произвольного листа, - по аналогии с одноименным методом из ComExcelDocument_RU.
По непонятным для меня причинам всё семейство SysExcel объявлено как выполняющееся сугубо на клиенте. В моем случае это ограничение снято, чтобы можно было формировать файлы Excel в пакетных заданиях, выполняющихся на сервере, однако, в выложенном проекте эти изменения не отражены.
Angehängte Dateien
Dateityp: rar SysExcel_via_NET.rar (17,4 KB, 1438x aufgerufen)
This post has been rated by: mazzy (5), eugene egorov (2), raz (15), ZVV (5), naPmu3aH (1), Logger (18), lev (10), ziva (2), AvrDen (1), Bega (10), perestoronin (1), MikeR (10), IvanS (1), Stainless (1), S.Kuskov (15), suicest (1), Kabardian (4), Dark Light (2), Melkiades (1).
Alt 05.09.2011, 13:51   #2  
Logger ist offline
Logger
Участник
Лучший по профессии 2015
Лучший по профессии 2014
 
3.995 / 3293 (117) ++++++++++
Registriert seit: 12.10.2004
Ort: Москва
Blog-Einträge: 2
Кстати, а кто нибудь решил проблему с некорректной работой объединения ячеек через .Net ?
(Метод Union из Excel в \Classes\SysDataExcelCOM\ )
Alt 05.09.2011, 15:47   #3  
Stainless ist offline
Stainless
Участник
MCBMSS
Columbus IT
 
34 / 114 (4) +++++
Registriert seit: 26.01.2007
Как раз очень интересует серверный режим работы, какие были подводные камни при переводе? (кроме изменения режима выполнения SysExcel на CalledFrom и простановке необходимых Permissions)
Alt 05.09.2011, 18:01   #4  
gl00mie ist offline
gl00mie
Участник
MCBMSS
Most Valuable Professional
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
3.684 / 5813 (201) ++++++++++
Registriert seit: 28.11.2005
Ort: Москва
Blog-Einträge: 3
Подводный камень только один: решить, когда создавать SysExcelApplication нужно все-таки именно на клиенте, поскольку один и тот же серверный код может работать как в пакете, так и интерактивно, и в последнем случае, очевидно, Excel должен запускаться на клиентской машине. Я это решил так:
X++:
public static client server SysExcelApplication_NET construct(ClassRunMode _contructOnTier = ClassRunMode::Client)
{
    SysExcelApplication_NET ret;
    ;
    switch (_contructOnTier)
    {
        case ClassRunMode::Called :
        case ClassRunMode::ClientOrServer :
            ret = new SysExcelApplication_NET();
            break;
        case ClassRunMode::Client :
            ret = classFactory::makeObjectOnClient( classnum(SysExcelApplication_NET) );
            break;
        case ClassRunMode::Server :
            ret = classFactory::makeObjectOnServer( classnum(SysExcelApplication_NET) );
            break;
        default :
            throw error( Error::unsupportedEnumValue( _contructOnTier ) );
    }
    return ret;
}
public static client server SysExcelApplication construct()
{
    SysExcelApplication     ret;
    COM                     excel;
    real                    excelVersion;
    ;
    if (SysExcel::mustInteropViaNET())
    {
        return SysExcelApplication_NET::construct( clientKind() == ClientType::Server ? ClassRunMode::Server : ClassRunMode::Client );
    }
    // ...
Запрос всех InteropPermission'ов для взаимодействия с CLR на сервере в модификации реализован, так что вызывающий код об этом может не заботиться.
Alt 08.10.2012, 09:41   #5  
Masel ist offline
Masel
Участник
 
39 / 537 (18) +++++++
Registriert seit: 19.09.2007
Zitat:
Zitat von gl00mie Beitrag anzeigen
Подводный камень только один: решить, когда создавать SysExcelApplication нужно все-таки именно на клиенте, поскольку один и тот же серверный код может работать как в пакете, так и интерактивно, и в последнем случае, очевидно, Excel должен запускаться на клиентской машине. Я это решил так:
X++:
public static client server SysExcelApplication_NET construct(ClassRunMode _contructOnTier = ClassRunMode::Client)
{
    SysExcelApplication_NET ret;
    ;
    switch (_contructOnTier)
    {
        case ClassRunMode::Called :
        case ClassRunMode::ClientOrServer :
            ret = new SysExcelApplication_NET();
            break;
        case ClassRunMode::Client :
            ret = classFactory::makeObjectOnClient( classnum(SysExcelApplication_NET) );
            break;
        case ClassRunMode::Server :
            ret = classFactory::makeObjectOnServer( classnum(SysExcelApplication_NET) );
            break;
        default :
            throw error( Error::unsupportedEnumValue( _contructOnTier ) );
    }
    return ret;
}
public static client server SysExcelApplication construct()
{
    SysExcelApplication     ret;
    COM                     excel;
    real                    excelVersion;
    ;
    if (SysExcel::mustInteropViaNET())
    {
        return SysExcelApplication_NET::construct( clientKind() == ClientType::Server ? ClassRunMode::Server : ClassRunMode::Client );
    }
    // ...
Запрос всех InteropPermission'ов для взаимодействия с CLR на сервере в модификации реализован, так что вызывающий код об этом может не заботиться.
При создании книги (workbook) из шаблона на сервере аксапта кидает Exception::ClrError. Что я делаю не так? Кстати если создавать книгу не из шаблона, то все отрабатывает корректно.
Права на шаблон у учетки АОСа FullControl.
Alt 08.10.2012, 11:17   #6  
Masel ist offline
Masel
Участник
 
39 / 537 (18) +++++++
Registriert seit: 19.09.2007
Нашел решение в интернете.

Решение:
для Windows 2008 Server x64 создать папку C:\Windows\SysWOW64\config\systemprofile\Desktop
для Windows 2008 Server x86 создать папку C:\Windows\System32\config\ systemprofile\Desktop


Я даже не знаю, что сказать на этот счет, у меня просто нет слов. Microsoft ***
Как я рад, что нашел это решение на 5-й странице поиска, с ужасом думаю что мог ее пролистать
This post has been rated by: Logger (3), Denicce (2), propeller (1).
Alt 08.10.2012, 20:38   #7  
gl00mie ist offline
gl00mie
Участник
MCBMSS
Most Valuable Professional
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
3.684 / 5813 (201) ++++++++++
Registriert seit: 28.11.2005
Ort: Москва
Blog-Einträge: 3
Можно было ограничиться поиском по форуму: Сохранение документа Excel
Alt 22.10.2012, 08:37   #8  
pasha_isaev ist offline
pasha_isaev
Участник
 
12 / 12 (1) ++
Registriert seit: 21.03.2006
Ort: Барнаул
Не работает Microsoft.Office.Interop.Excel._Application.Union()
Zitat:
Внимание! Работу с Excel вашего или чужого кода через .NET нужно тщательно тестировать, к примеру, у меня не заработало объединение ячеек, используемое в \Classes\SysDataExcelCOM\addLookup, которое на ура отрабатывает через COM
Уважаемые, решил ли кто-нибудь эту проблему? Какие танцы с бубном требуются для объединения разрозненных ячеек через .NET?
Alt 06.03.2013, 11:36   #9  
Bega ist offline
Bega
Участник
Benutzerbild von Bega
 
382 / 444 (15) +++++++
Registriert seit: 18.08.2005
Ort: Москва
Почему-то при работе через .NET на клиенте, процесс Excel остается в памяти, даже когда пользователь закрывает Excel. Этот процесс исчезает только с выходом из DAX. Так что если пользователь весь день запускает отчеты, то у него может закончится память, да и некрасиво это.

Сравнивал с аналогичным вызовом через COM, там процесс сразу исчезает после закрытия Excel.

Есть идеи, как это побороть?
Вот код, который воспроизводит проблему (специально вытащил вызовы .NET из классов gl00mie для наглядности):
X++:
Microsoft.Office.Interop.Excel.ApplicationClass application_net = new Microsoft.Office.Interop.Excel.ApplicationClass();
Microsoft.Office.Interop.Excel.Workbooks        workbooks_net;
;
workbooks_net = application_net.get_Workbooks();
workbooks_net.Add("");
application_net.set_Visible(true);
Alt 06.03.2013, 11:55   #10  
Logger ist offline
Logger
Участник
Лучший по профессии 2015
Лучший по профессии 2014
 
3.995 / 3293 (117) ++++++++++
Registriert seit: 12.10.2004
Ort: Москва
Blog-Einträge: 2
Может попробовать принудительно запустить .Net сборку мусора ?
Обычно помогает.
Alt 06.03.2013, 11:57   #11  
Bega ist offline
Bega
Участник
Benutzerbild von Bega
 
382 / 444 (15) +++++++
Registriert seit: 18.08.2005
Ort: Москва
Zitat:
Zitat von Logger Beitrag anzeigen
Может попробовать принудительно запустить .Net сборку мусора ?
Обычно помогает.
Это как?
Alt 06.03.2013, 12:31   #12  
Logger ist offline
Logger
Участник
Лучший по профессии 2015
Лучший по профессии 2014
 
3.995 / 3293 (117) ++++++++++
Registriert seit: 12.10.2004
Ort: Москва
Blog-Einträge: 2
Ошибка чтения файлов XLS под Windows 7
https://groups.google.com/forum/?fro...ng/eNozbbwCZF0
и.т.п.
This post has been rated by: Bega (5).
Alt 06.03.2013, 12:36   #13  
Bega ist offline
Bega
Участник
Benutzerbild von Bega
 
382 / 444 (15) +++++++
Registriert seit: 18.08.2005
Ort: Москва
Действительно, вот такой вариант работает.
X++:
Microsoft.Office.Interop.Excel.ApplicationClass application_net = new Microsoft.Office.Interop.Excel.ApplicationClass();
    Microsoft.Office.Interop.Excel.Workbooks        workbooks_net;
    ;
    workbooks_net = application_net.get_Workbooks();
    workbooks_net.Add("");
    application_net.set_Visible(true);
    
    workbooks_net = null;
    application_net = null;
    
    System.GC::Collect();
This post has been rated by: Ace of Database (2).
Alt 06.03.2013, 13:08   #14  
LeonDerCom ist offline
LeonDerCom
Участник
 
45 / 20 (1) +++
Registriert seit: 08.10.2012
Bega
Попробуйте
X++:
application_net.finalize
Alt 06.03.2013, 14:16   #15  
Bega ist offline
Bega
Участник
Benutzerbild von Bega
 
382 / 444 (15) +++++++
Registriert seit: 18.08.2005
Ort: Москва
Zitat:
Zitat von LeonDerCom Beitrag anzeigen
Bega
Попробуйте
X++:
application_net.finalize
Нет такого метода.
Alt 06.03.2013, 15:21   #16  
LeonDerCom ist offline
LeonDerCom
Участник
 
45 / 20 (1) +++
Registriert seit: 08.10.2012
Bega
В данном случае не вчитался и подумал о ком объекте. А раз тут дотНет, то есть еще вот такой момент, в C# после Collect вызывал метод WaitForPendingFinalizers.
Alt 06.03.2013, 15:23   #17  
Bega ist offline
Bega
Участник
Benutzerbild von Bega
 
382 / 444 (15) +++++++
Registriert seit: 18.08.2005
Ort: Москва
Zitat:
Zitat von LeonDerCom Beitrag anzeigen
Bega
В данном случае не вчитался и подумал о ком объекте. А раз тут дотНет, то есть еще вот такой момент, в C# после Collect вызывал метод WaitForPendingFinalizers.
Да, видел этот метод, но без него тоже работает, посчитал что "wait" тут не нужно.
Alt 07.03.2013, 16:30   #18  
Bega ist offline
Bega
Участник
Benutzerbild von Bega
 
382 / 444 (15) +++++++
Registriert seit: 18.08.2005
Ort: Москва
Есть какой-то способ вставки в range массива, как это было возможно с COM?
Вот пример для COM, он работает:
X++:
ComExcelDocument_RU         comExcel;
    ArrayExtend_RU              arrayStr = new ArrayExtend_RU(Types::String, 10);
    ;
    comExcel = new ComExcelDocument_RU();
    comExcel.newFile("", false);
    
    arrayStr = new ArrayExtend_RU(Types::String, 2);
    arrayStr.value(1, "AAA");
    arrayStr.value(2, "БББ");
    
    comExcel.insertValue("A1:B1", arrayStr);
    
    comExcel.visible(true);
А для .NET не работает:
X++:
SysExcelApplication_NET     sysExcelApplication;
    SysExcelWorksheet_NET       sysExcelWorksheet;
    SysExcelRange_NET           range;
    ArrayExtend_RU              arrayStr = new ArrayExtend_RU(Types::String, 10);
    ;
    sysExcelApplication = SysExcelApplication_NET::construct();
    sysExcelApplication.workbooks().add("");
    sysExcelWorksheet = sysExcelApplication.worksheets().itemFromNum(1);
    arrayStr = new ArrayExtend_RU(Types::String, 2);
    arrayStr.value(1, "AAA");
    arrayStr.value(2, "БББ");
    range = sysExcelWorksheet.range("A1:B1");

    range.value2(arrayStr);

    sysExcelApplication.visible(true);
Пытался различными способами передать массив, прямая передача или упаковка через CLRInterop::getObjectForAnyType(arrayStr ) выдает ошибку о невозможности преобразования.
Alt 07.03.2013, 16:46   #19  
Bega ist offline
Bega
Участник
Benutzerbild von Bega
 
382 / 444 (15) +++++++
Registriert seit: 18.08.2005
Ort: Москва
Нашел способ через System.Array:
X++:
SysExcelApplication_NET     sysExcelApplication;
    SysExcelWorksheet_NET       sysExcelWorksheet;
    SysExcelRange_NET           range;
    System.Array                array;
    System.Type                 type;
    ;
    sysExcelApplication = SysExcelApplication_NET::construct();
    sysExcelApplication.workbooks().add("");
    sysExcelWorksheet = sysExcelApplication.worksheets().itemFromNum(1);
    
    type = System.Type::GetType('System.String');
    array = System.Array::CreateInstance(type, 2);
    
    array.SetValue(CLRInterop::getObjectForAnyType("AAA"), 0);
    array.SetValue(CLRInterop::getObjectForAnyType("БББ"), 1);
    
    range = sysExcelWorksheet.range("A1:B1");
    range.value2(array);
    
    sysExcelApplication.visible(true);
This post has been rated by: BOAL (2), Pustik (2), Logger (5), IvanS (1).
Alt 09.10.2013, 07:31   #20  
IvanS ist offline
IvanS
Участник
Benutzerbild von IvanS
 
241 / 44 (2) +++
Registriert seit: 30.06.2006
Ort: Екатеринбург
При открытии шаблона через workBooks_net у меня возникает сообщение, что файл был восстановлен. С чем это может быть связано?
Выяснил, что такое поведение связано с шаблонами 2007 офиса. С 2003 нормально работает

Geändert von IvanS (09.10.2013 um 08:24 Uhr)
Stichworte
.net, ax2009, excel, законченный пример, полезное

 

Ähnliche Themen
Thema Autor Forum Antworten Letzter Beitrag
проблема использования Excel через clr Batuev Artem DAX: Программирование 8 22.08.2011 18:01
AX.NET: интеграция .NET-приложений с Аксаптой и (будущие) возможности облачных вычислений gl00mie DAX: Программирование 2 23.04.2010 00:47
Импорт даты через Excel OliaM DAX: Функционал 2 13.12.2007 10:32
Экспорт в Excel через WorkBooks.OpenText() Владимир Максимов DAX: Программирование 2 09.04.2004 17:16
Чтение Excel-ячейки в Аксапте (2.5) через COM AKIS DAX: Программирование 3 25.03.2004 20:18

Forumregeln
Es ist Ihnen nicht erlaubt, neue Themen zu verfassen.
Es ist Ihnen nicht erlaubt, auf Beiträge zu antworten.
Es ist Ihnen nicht erlaubt, Anhänge hochzuladen.
Es ist Ihnen nicht erlaubt, Ihre Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Gehe zu

Рейтинг@Mail.ru
Alle Zeitangaben in WEZ +3. Es ist jetzt 06:20 Uhr.
Powered by vBulletin® Version 3.8.5 (Deutsch)
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.