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

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 07.11.2008, 13:21   #1  
Gustav is offline
Gustav
Moderator
Аватар для Gustav
SAP
Лучший по профессии 2009
 
1,858 / 1152 (42) ++++++++
Регистрация: 24.01.2006
Адрес: Санкт-Петербург
Записей в блоге: 19
? э-хе-хе...
Испытываю возобновление интереса к теме и вот в связи с чем. ADODB.Recordset имеет полезнейшие свойства Filter и Sort, которыми можно эффективно пользоваться, фильтруя исходный набор или изменяя порядок записей исходного Recordset'а и далее перебирая в цикле нужные записи в нужном порядке.

Резонно было бы предположить, хотя про это нигде не сказано в справке, что методом CopyFromRecordset должен выгружаться набор записей с учетом фильтрации и сортировки. Увы, при управлении Excel из Аксапты этого не происходит:

X++:
static void Job103(Args _args)
{
    #CCADO

    ComExcelDocument_RU doc = new ComExcelDocument_RU();
    COM                 rst = new COM('ADODB.Recordset');

    COM     xlApp;
    COM     wbook;
    COM     activeSheet;
    COM     range;
    COM     flds,fld;

    int     i;
    ;

    doc.NewFile('',false);
    wbook = doc.getComDocument();

    xlApp = wbook.Parent();
    activeSheet = xlApp.ActiveSheet();

    flds = rst.Fields();

    flds.Append('myField1', #adVarChar, 50);
    flds.Append('myField2', #adInteger);
    
    rst.Open();

    for (i=1;i<=1000;i++)
    {
        rst.AddNew();
            fld = flds.Item(0); fld.Value(int2str(i));
            fld = flds.Item(1); fld.Value(i*2);
        rst.Update();
    }

    rst.Filter("myField1 Like '*24*'");
    rst.Sort('myField1 DESC');

    rst.MoveFirst();

    range = activeSheet.Range('A1');
    range.CopyFromRecordset(rst, 300);

    range = activeSheet.Range('A1000');
    range.CopyFromRecordset(rst, 300);

    doc.visible(true);

    
    // чтобы показать, что набор действительно фильтруется и сортируется
    rst.MoveFirst();
    while (! rst.EOF())
    {
        info(strFmt('%1 --- %2', 
                    new CCADOField( flds.Item(0) ).value(),
                    new CCADOField( flds.Item(1) ).value()));
        rst.MoveNext();
    }
}
Поведение метода CopyFromRecordset в этом примере не соответствует ожиданиям. Он не учитывает не только сортировку и фильтрацию, но и декларированное в справке продвижение указателя текущей записи. Так, по здравой логике, первый оператор "range.CopyFromRecordset(rst, 300);" должен вывести в Excel первые 300 записей и установить указатель на 301-ю. Второй же оператор "range.CopyFromRecordset(rst, 300);" должен вывести следующие 300 записей: с 301-й по 600-ю и остановиться на 601-й.

Но этого не происходит. Вместо этого - и начиная с ячейки A1, и начиная с ячейки A1000 - одинаково выводятся первые 300 записей исходного набора. А хотелось бы, чтобы вывелись только 20 записей с ячейки A1, т.е. те записи, которые пример выводит в окно Infolog.

Возможно мои претензии необоснованы и CopyFromRecordset должен себя вести именно так, как ведет себя в этом примере? Я уже было засомневался, вернее, почти отказался от своих "претензий", но решился на еще одну проверку - в самом Excel на VBA:
Код:
 
Sub Job103_VBA()

    Dim i As Integer
    
    Dim rst As Object
    Dim flds As Object
    
    Dim xlApp As Excel.Application

    Set rst = CreateObject("ADODB.Recordset")
    'я сознательно создал rst через CreateObject, а не как New ADODB.Recordset, 
    'чтобы не искать ссылку на ADO через Tools\References    
    
    Set flds = rst.Fields
    
    flds.Append "myField1", 200, 50 '200 = adVarChar
    flds.Append "myField2", 3 '3 = adInteger
    
    rst.Open
    
    For i = 1 To 1000
        rst.AddNew
            rst.Fields(0).Value = i
            rst.Fields(1).Value = i * 2
        rst.Update
    Next i
    
    rst.Filter = "myField1 Like '*24*'"
    rst.Sort = "myField1 DESC"
    
    rst.MoveFirst
    
    'Set xlApp = New Excel.Application
    Set xlApp = Application
    
    xlApp.Workbooks.Add
      
    xlApp.Range("A1").CopyFromRecordset rst, 300
    xlApp.Range("A1000").CopyFromRecordset rst, 300
    
    xlApp.Visible = True
    
End Sub
Что скажете о результате? Он такой, как хотелось! Ура? Увы, нет. Закомментируйте строку "Set xlApp = Application" и раскомментируйте строку выше, т.е. должно стать вот так:
Код:
 
    Set xlApp = New Excel.Application
    'Set xlApp = Application
Таким образом, теперь мы из Excel создаем другой Excel и выводим рекордсет в этот другой. Результат такой же, как при выводе из Аксапты - не такой, как хочется.

Есть ли у кого какие-нибудь соображения? Может, кто-нибудь интересующийся продвинуто заглянет какими-нибудь крутыми вьюерами в тайны происходящих процессов COM-автоматизации? Может быть удастся победить ситуацию использованием каких-нибудь COMDispFunction?


P.S. Проделал даже такой финт. Создал шаблон xlt, в который зашил VBA-процедуру:
Код:
 
Sub myCopyFromRecordset(ByVal rng As Range, ByVal rst As ADODB.Recordset, ByVal maxRows As Integer)
    rng.CopyFromRecordset rst, maxRows
End Sub
Из Аксапты создал новый файл на базе этого шаблона и вызвал процедуру строкой:
X++:
    xlApp.Run('myCopyFromRecordset', range, rst, 300);
Результат - тоже не тот
Старый 07.11.2008, 20:12   #2  
sukhanchik is offline
sukhanchik
Administrator
Аватар для sukhanchik
MCBMSS
Злыдни
Лучший по профессии 2015
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
3,283 / 3491 (123) ++++++++++
Регистрация: 13.06.2004
Адрес: Москва
Цитата:
Сообщение от Gustav Посмотреть сообщение
Резонно было бы предположить, хотя про это нигде не сказано в справке, что методом CopyFromRecordset должен выгружаться набор записей с учетом фильтрации и сортировки.
Для тех, кто программировал в Access еще в DAO (а в общем-то DAO можно считать прародителем ADO) такое предположение отнюдь не резонно. Методы Filter и Sort действовали ПОСЛЕ выборки, а метод CopyFromRecordset копировал именно все записи выборки (он совершенно не собирался смотреть на методы Filter и Sort). Именно поэтому в Access приветствовалось программирование через SQL-запросы, а не через методы работы с таблицами.

Я удивлен другим. Я удивлен - что CopyFromRecordset все-таки может копировать с учетом фильтрации - но об этом видимо "помнит" только текущее приложение - т.е. поддержка реализована не на уровне "ядра" ADO
__________________
Возможно сделать все. Вопрос времени
Теги
ado, comvariant, excel, faq, odbc, sql, интеграция, прямой доступ, формат дат, экспорт, экспорт в excel

 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
Вспомогательный класс для импорта из Excel через ADO gl00mie DAX: База знаний и проекты 80 10.04.2017 10:55
gl00mie: Read Excel table via ADO Blog bot DAX Blogs 2 09.04.2010 08:32
C# and AX Development: Using ADO for interfacing AX with an external database Blog bot DAX Blogs 0 05.08.2008 05:18
casperkamal: Using ADO to read from Excel in Microsoft Dynamics Ax Blog bot DAX Blogs 2 14.05.2007 11:59

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

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

Рейтинг@Mail.ru
Часовой пояс GMT +3, время: 08:03.
Powered by vBulletin® v3.8.5. Перевод: zCarot
Контактная информация, Реклама.