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

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 25.09.2008, 11:49   #1  
niktata is offline
niktata
Участник
 
17 / 10 (1) +
Регистрация: 23.07.2008
Адрес: Санкт-Петербург
Нужно сделать выборку из нескольких таблиц (в данном случае из четырех).
В продолжение темы Импорт бинарных данных

Столкнулся еще с одной проблемой при импорте из 1С а AX. Буду благодарен, если кто-нибудь поможет..
Нужно сделать выборку из нескольких таблиц (в данном случае из четырех). Т.е. нужно выбрать все образования для физических лиц из таблицы Справочник.ФизическиеЛица.Образование и для выбранных образований вытащить из таблиц Справочник.ФизическиеЛица, Справочник.УчебныеЗаведения и ФизическиеЛицаОбразование.ВидОбразования код сотрудника, название учебного заведения и вид образования соответственно. Код следующий:
X++:
    Text =  "ВЫБРАТЬ "
             +"   ФизическиеЛица.Код                                    КАК Код,"
             +"   УчебныеЗаведения.Наименование                         КАК УчебноеЗаведение,"
             +"   ВидыОбразованияФизЛиц.Наименование                    КАК ВидОбразования,"
             +"   ФизическиеЛицаОбразование.Диплом                      как Диплом,  "
             +"   ФизическиеЛицаОбразование.ГодОкончания                как ГодОкончания,"
             +"   ФизическиеЛицаОбразование.Квалификация                как Квалификация"
          +"  ИЗ"
             +"   Справочник.ФизическиеЛица.Образование КАК ФизическиеЛицаОбразование"
             +"   ЛЕВОЕ СОЕДИНЕНИЕ Справочник.ФизическиеЛица КАК ФизическиеЛица"
             +"   ПО ФизическиеЛицаОбразование.Ссылка = ФизическиеЛица.Ссылка"
             +"   ЛЕВОЕ СОЕДИНЕНИЕ Справочник.УчебныеЗаведения КАК УчебныеЗаведения"
             +"   ПО ФизическиеЛицаОбразование.УчебноеЗаведение = УчебныеЗаведения.Ссылка"
             +"   ЛЕВОЕ СОЕДИНЕНИЕ Справочник.ВидыОбразованияФизЛиц КАК ВидыОбразованияФизЛиц"
             +"   ПО ФизическиеЛицаОбразование.ВидОбразования = ВидыОбразованияФизЛиц.Ссылка"
          +"  ГДЕ"
             +"   ФизическиеЛица.Ссылка <> \"000000001\"";
    Query.Text(Text);

    // Выполнение запроса
    Result = Query.Execute();
    Choose = Result.Choose();

    // Выборка результата выполнения запроса
    While (Choose.Next())
    {
        i++;
        info(strFmt('%1 - %2 - %3', i, Choose.(), Choose.(), Choose.()));
    }
Код вылетает на строчке с info(), т.е. при обращении к Choose.УчебноеЗаведение() с ошибкой "Ошибка времени выполнения. : Вариантный тип, возвращенный методом COM-объекта, не поддерживается.".
Вылетает, как я понимаю, из-за того, что не у всех строчек таблицы Справочник.ФизическиеЛица.Образование заполнено поле УчебноеЗаведение

Пробовал делать так:
X++:
    While (Choose.Next())
    {
        i++;
        if (Choose.())
            info(strFmt('%1 - %2 - %3', i, Choose.(), Choose.(), Choose.()));
    }
но тогда код вываливается на if (Choose.УчебноеЗаведение()). Как же от этого избавиться?

Пробовал также делать эту выборку за несколько заходов:
1. Сначала выбирать из таблицы Справочник.ФизическиеЛица.Образование все записи, у которых заполнено поле УчебноеЗаведение (точнее ссылка на таблицу Справочник.УчебныеЗаведения).
2. Потом выбирать все записи, у которых заполнено поле ВидОбразования (ссылка на таблицу Справочник.ВидыОбразованияФизЛиц)
3. Связывать эти 2 выборки по ссылке из этой таблицы (типа аксаптовского RecId), но ссылка опять же имеет бинарный формат, который мне не удается как-либо обработать (преобразовать в текст или сравнить например). В общем опять все уперлось в то, с чего я и начал. Как обработать binary в ax

Последний раз редактировалось niktata; 25.09.2008 в 12:24.
Старый 25.09.2008, 12:31   #2  
ice is offline
ice
Участник
Аватар для ice
Лучший по профессии 2014
 
1,732 / 406 (17) +++++++
Регистрация: 23.03.2006
возможно стоит использовать английские аналоги вызываемых методов, вместо Choose.Код(), Choose.УчебноеЗаведение(), Choose.ВидОбразования()
Старый 25.09.2008, 12:54   #3  
niktata is offline
niktata
Участник
 
17 / 10 (1) +
Регистрация: 23.07.2008
Адрес: Санкт-Петербург
Да вроде с русскими названиями аксапта нормально работает, не ругается. Тем более вылетает код не на 1ой строчке, а как раз на той, в которой не заполнено поле Справочник.УчебныеЗаведения. В моем случае это вторая строчка. В приложении это поле выделено.
Нажмите на изображение для увеличения
Название: query_hrm.JPG
Просмотров: 805
Размер:	197.7 Кб
ID:	3752
Старый 25.09.2008, 13:38   #4  
_scorp_ is offline
_scorp_
Участник
Аватар для _scorp_
MCBMSS
 
488 / 369 (13) ++++++
Регистрация: 25.07.2007
Адрес: Москва
X++:
,   , - ,       ..
Вряд ли. Лучше сначала откройте конфигуратор 1С. Создайте обработку. Вызовите мастер запросов, в нем создайте мышкой такой запрос который Вам нужен. Отладьте его в 1С, а потом уже используйте в аксапте.

p.s. По вопросом программирования 1С лучше полбзуйтесь сайтом http://www.forum.mista.ru/, а то тут люди и испугаться могут от запросов 1С, очень уж у них синтаксис страшный на мой взгляд
Старый 25.09.2008, 16:04   #5  
niktata is offline
niktata
Участник
 
17 / 10 (1) +
Регистрация: 23.07.2008
Адрес: Санкт-Петербург
Ладно, буду копать. Если разберусь - отпишусь. Может кому-нибудь пригодится.. Спасибо еще раз
Старый 25.09.2008, 19:20   #6  
Владимир Максимов is offline
Владимир Максимов
Участник
КОРУС Консалтинг
 
1,701 / 1195 (43) ++++++++
Регистрация: 13.01.2004
Записей в блоге: 3
Если это запрос через COM-объекты, то попробуй принимать значения как тип ComVariant

X++:
ComVariant retVal;
;

retVal = Choose.();

// Если ожидается значение типа int
print retVal.int();
pause;

// Если ожидается значение типа str
print retVal.bStr ();
pause;
Можно сделать анализ типа возвращенного значения через свойство comVariant.variantType() для написания универсальной обработки

Вот выдрал метод по преобразованию типов ComVariant из своего класса на Ax2.5

X++:
// Преобразование полученного значения
anyType getValue(ComVariant _comVariant)
{
//    Com     comValue;
    ;

    switch (_comVariant.variantType())
    {
    case COMVariantType::VT_BOOL :
        return _comVariant.boolean();       // boolean
    case COMVariantType::VT_BSTR :
        return _comVariant.bStr();          // str
    case COMVariantType::VT_UI1 :
        return _comVariant.byte();          // int
    case COMVariantType::VT_I1 :
        return _comVariant.char();          // int
    case COMVariantType::VT_CY :
        return _comVariant.currency();      // real
    case COMVariantType::VT_DATE :
        return _comVariant.date();          // date
    case COMVariantType::VT_DECIMAL :
        return _comVariant.decimal();       // real
    case COMVariantType::VT_R8 :
        return _comVariant.double();        // real
    case COMVariantType::VT_R4 :
        return _comVariant.float();         // real
    case COMVariantType::VT_DISPATCH :
//        return _comVariant.iDispatch();           // дескриптор COM-интерфейса. Число.
        return COM::createFromVariant(_comVariant); // Преобразую в ссылку на объект
    case COMVariantType::VT_I4 :            // int
        return _comVariant.int();
//        return _comVariant.long();          // теоретически, это должно быть VT_I8, но такого значения нет, поэтому VT_I4 читается как int()
    case COMVariantType::VT_UNKNOWN :
        //return _comVariant.iUnknown();                // дескриптор COM-интерфейса. Число.
        return COM::createFromVariant(_comVariant);     // Преобразую в ссылку на объект
    case COMVariantType::VT_ERROR :
        return _comVariant.sCode();         // int
    case COMVariantType::VT_I2 :
        return _comVariant.short();         // int

    case COMVariantType::VT_UI4 :
        return _comVariant.uInt();         // int
        //return _comVariant.uLong();         // теоретически, это должно быть VT_UI8, но такого значения нет, поэтому VT_I4 читается как int()
    case COMVariantType::VT_UI2 :
        return _comVariant.uShort();        // int
    case COMVariantType::VT_VARIANT :
        return _comVariant.variant();       // COMVariant
    case COMVariantType::VT_SAFEARRAY :
        return _comVariant.safeArray();     // array
    default :
        throw error(strFmt("Неизвестны правила обработки типа %1", _comVariant.variantType()));

    }
}
За это сообщение автора поблагодарили: niktata (1).
Старый 26.09.2008, 10:57   #7  
ice is offline
ice
Участник
Аватар для ice
Лучший по профессии 2014
 
1,732 / 406 (17) +++++++
Регистрация: 23.03.2006
по поводу самого импорта из 1с:
зачем вообще придумывать себе такую проблему, 1с способна спокойно записывать данные в таблицы SQL без особых проблем. сделайте обмен таким образом и ничего изобретать не придется, если конечно не стоит задача динамических отчетов в аксапте с данными из 1с

Последний раз редактировалось ice; 26.09.2008 в 10:59.
Старый 26.09.2008, 11:02   #8  
lev is offline
lev
Ищущий знания...
Аватар для lev
Oracle
MCBMSS
Axapta Retail User
 
1,723 / 491 (20) +++++++
Регистрация: 18.01.2005
Адрес: Москва
Цитата:
Сообщение от ice Посмотреть сообщение
по поводу самого импорта из 1с:
зачем вообще придумывать себе такую проблему, 1с способна спокойно записывать данные в таблицы SQL без особых проблем. сделайте обмен таким образом и ничего изобретать не придется, если конечно не стоит задача динамических отчетов в аксапте с данными из 1с
Полностью поддерживаю. Самый простой и надежный вариант.
__________________
"Страх перед возможностью ошибки не должен отвращать нас от поисков истины." (с)
С Уважением,
Елизаров Артем
Старый 26.09.2008, 11:16   #9  
_scorp_ is offline
_scorp_
Участник
Аватар для _scorp_
MCBMSS
 
488 / 369 (13) ++++++
Регистрация: 25.07.2007
Адрес: Москва
Цитата:
Сообщение от ice Посмотреть сообщение
по поводу самого импорта из 1с:
зачем вообще придумывать себе такую проблему, 1с способна спокойно записывать данные в таблицы SQL без особых проблем. сделайте обмен таким образом и ничего изобретать не придется, если конечно не стоит задача динамических отчетов в аксапте с данными из 1с
Это в 1С 7.7 было все просто. Там были такие файлики 1Сv7.dd или 1Cv7.dds (если версия SQL) где была описана вся структура данных. В восьмерке все намного сложнее. Если вы хотите сделать надежный обмен данными - нужно использовать OLE. Как Вы, например, будете работать с перечислениями, с константами, с планами видов характеристик, если будете работать напрямую через SQL? Ну и самый веский аргумент - если когда нибудь решат закрыть базу или перейти на другую версию - весь импорт придется переписывать, т.к. 1С сформирует совсем другую структуру данных в SQL. Структура может будет и такой же, но все названия таблиц, названия полей будут другими. Да и 1С может быть не SQL-ной.
Старый 26.09.2008, 11:46   #10  
ice is offline
ice
Участник
Аватар для ice
Лучший по профессии 2014
 
1,732 / 406 (17) +++++++
Регистрация: 23.03.2006
Цитата:
Сообщение от _scorp_ Посмотреть сообщение
Это в 1С 7.7 было все просто. Там были такие файлики 1Сv7.dd или 1Cv7.dds (если версия SQL) где была описана вся структура данных. В восьмерке все намного сложнее. Если вы хотите сделать надежный обмен данными - нужно использовать OLE. Как Вы, например, будете работать с перечислениями, с константами, с планами видов характеристик, если будете работать напрямую через SQL? Ну и самый веский аргумент - если когда нибудь решат закрыть базу или перейти на другую версию - весь импорт придется переписывать, т.к. 1С сформирует совсем другую структуру данных в SQL. Структура может будет и такой же, но все названия таблиц, названия полей будут другими. Да и 1С может быть не SQL-ной.
речь идет вовсе не о эскуэльной версии 1с. речь о том что можно сознать таблицы для обмена инфой в sql.
Старый 30.09.2008, 09:42   #11  
niktata is offline
niktata
Участник
 
17 / 10 (1) +
Регистрация: 23.07.2008
Адрес: Санкт-Петербург
Всем спасибо за помощь, вроде разобрался.

Сделал несколько функций:
X++:
    str strPropertyGet(str _property)
    {
        str             ret;
        ComVariant      varOut = new ComVariant(ComVariantInOut::Out_retVal,ComVariantType::VT_BSTR);
        ComDispFunction _propertyGet = new COMDispFunction(Choose, _property, COMDispContext::PropertyGet);
        ;
        ret = (_propertyGet.call(varOut) ? "" : varOut.bStr());
        varOut.finalize();
        _propertyGet.finalize();
        return strLTrim(strRTrim(ret));
    }

    int intPropertyGet(str _property)
    {
        int             ret;
        ComVariant      varOut = new ComVariant(ComVariantInOut::Out_retVal,ComVariantType::VT_I4);
        ComDispFunction _propertyGet = new COMDispFunction(Choose, _property, COMDispContext::PropertyGet);
        ;
        ret = (_propertyGet.call(varOut) ? 0 : varOut.int());
        varOut.finalize();
        _propertyGet.finalize();
        return ret;
    }

    date datePropertyGet(str _property)
    {
        date            ret;
        ComVariant      varOut = new ComVariant(ComVariantInOut::Out_retVal,ComVariantType::VT_DATE);
        ComDispFunction _propertyGet = new COMDispFunction(Choose, _property, COMDispContext::PropertyGet);
        ;
        ret = (_propertyGet.call(varOut) ? dateNull() : varOut.date());
        varOut.finalize();
        _propertyGet.finalize();
        return ret;
    }
Для того, чтобы код не вываливался при попытке достать изображение, если изображение отсутвует пришлось сделать немного подругому. Возможно, кривовато, но работает

X++:
        emplId = strPropertyGet("Код");
        select forupdate firstonly firstfast
            emplTable
                where emplTable.EmplId == emplId;
        select forupdate firstonly firstfast companyImage
            where companyImage.RefRecId == emplTable.RecId;

        retVal              = new ComVariant(ComVariantInOut::Out_retVal, ComVariantType::VT_DISPATCH);
        propertyGet         = new COMDispFunction(Choose, "Хранилище", COMDispContext::PropertyGet);

        propertyGet.call(retVal);

        if (retVal.variantType() != ComVariantType::VT_NULL)
        {
            pic = Choose.(); // ХранилищеДополнительнойИнформации.Хранилище как Хранилище
            kart = con.NewObject("Картинка");
            kart = pic.();
            kart.("C:\\tmp.jpg");
            binData = new BinData();
            binData.loadFile("C:\\tmp.jpg");
            cont = binData.getData();

            companyImage.RefTableId     = 103;
            companyImage.RefRecId       = emplTable.RecId;
            companyImage.HasImage       = NoYes::Yes;
            companyImage.RefCompanyId   = 'etl';
            companyImage.Image          = cont;

            if (companyImage.RecId)
                emplTable.update();
            else
                companyImage.insert();
        }
        retVal.finalize();
        propertyGet.finalize();
Теги
интеграция, 1c

 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
Как сделать фильтр по группе пользователей? Zabr DAX: Программирование 12 08.04.2009 11:40
Перебор всех таблиц, имеющих поле определенного типа AKIS-Falcon DAX: Программирование 8 11.02.2005 17:07
Синхронизация таблиц при изменении EDT z_av DAX: Программирование 1 16.12.2004 11:55
Передача нескольких временных таблиц в отчет Pegiy DAX: Программирование 5 03.06.2004 17:44
Связывание нескольких таблиц jan_psn DAX: Программирование 11 18.11.2003 05:23

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

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

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