25.09.2008, 11:49 | #1 |
Участник
|
Нужно сделать выборку из нескольких таблиц (в данном случае из четырех).
В продолжение темы Импорт бинарных данных
Столкнулся еще с одной проблемой при импорте из 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.())); } Вылетает, как я понимаю, из-за того, что не у всех строчек таблицы Справочник.ФизическиеЛица.Образование заполнено поле УчебноеЗаведение Пробовал делать так: X++: While (Choose.Next()) { i++; if (Choose.()) info(strFmt('%1 - %2 - %3', i, Choose.(), Choose.(), Choose.())); } Пробовал также делать эту выборку за несколько заходов: 1. Сначала выбирать из таблицы Справочник.ФизическиеЛица.Образование все записи, у которых заполнено поле УчебноеЗаведение (точнее ссылка на таблицу Справочник.УчебныеЗаведения). 2. Потом выбирать все записи, у которых заполнено поле ВидОбразования (ссылка на таблицу Справочник.ВидыОбразованияФизЛиц) 3. Связывать эти 2 выборки по ссылке из этой таблицы (типа аксаптовского RecId), но ссылка опять же имеет бинарный формат, который мне не удается как-либо обработать (преобразовать в текст или сравнить например). В общем опять все уперлось в то, с чего я и начал. Как обработать binary в ax Последний раз редактировалось niktata; 25.09.2008 в 12:24. |
|
25.09.2008, 12:31 | #2 |
Участник
|
возможно стоит использовать английские аналоги вызываемых методов, вместо Choose.Код(), Choose.УчебноеЗаведение(), Choose.ВидОбразования()
|
|
25.09.2008, 12:54 | #3 |
Участник
|
Да вроде с русскими названиями аксапта нормально работает, не ругается. Тем более вылетает код не на 1ой строчке, а как раз на той, в которой не заполнено поле Справочник.УчебныеЗаведения. В моем случае это вторая строчка. В приложении это поле выделено.
|
|
25.09.2008, 13:38 | #4 |
Участник
|
X++: , , - , .. p.s. По вопросом программирования 1С лучше полбзуйтесь сайтом http://www.forum.mista.ru/, а то тут люди и испугаться могут от запросов 1С, очень уж у них синтаксис страшный на мой взгляд |
|
25.09.2008, 16:04 | #5 |
Участник
|
Ладно, буду копать. Если разберусь - отпишусь. Может кому-нибудь пригодится.. Спасибо еще раз
|
|
25.09.2008, 19:20 | #6 |
Участник
|
Если это запрос через COM-объекты, то попробуй принимать значения как тип ComVariant
X++: ComVariant retVal; ; retVal = Choose.(); // Если ожидается значение типа int print retVal.int(); pause; // Если ожидается значение типа str print retVal.bStr (); pause; Вот выдрал метод по преобразованию типов 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 |
Участник
|
по поводу самого импорта из 1с:
зачем вообще придумывать себе такую проблему, 1с способна спокойно записывать данные в таблицы SQL без особых проблем. сделайте обмен таким образом и ничего изобретать не придется, если конечно не стоит задача динамических отчетов в аксапте с данными из 1с Последний раз редактировалось ice; 26.09.2008 в 10:59. |
|
26.09.2008, 11:02 | #8 |
Ищущий знания...
|
Цитата:
Сообщение от ice
по поводу самого импорта из 1с:
зачем вообще придумывать себе такую проблему, 1с способна спокойно записывать данные в таблицы SQL без особых проблем. сделайте обмен таким образом и ничего изобретать не придется, если конечно не стоит задача динамических отчетов в аксапте с данными из 1с
__________________
"Страх перед возможностью ошибки не должен отвращать нас от поисков истины." (с) С Уважением, Елизаров Артем |
|
26.09.2008, 11:16 | #9 |
Участник
|
Цитата:
Сообщение от ice
по поводу самого импорта из 1с:
зачем вообще придумывать себе такую проблему, 1с способна спокойно записывать данные в таблицы SQL без особых проблем. сделайте обмен таким образом и ничего изобретать не придется, если конечно не стоит задача динамических отчетов в аксапте с данными из 1с |
|
26.09.2008, 11:46 | #10 |
Участник
|
Цитата:
Сообщение от _scorp_
Это в 1С 7.7 было все просто. Там были такие файлики 1Сv7.dd или 1Cv7.dds (если версия SQL) где была описана вся структура данных. В восьмерке все намного сложнее. Если вы хотите сделать надежный обмен данными - нужно использовать OLE. Как Вы, например, будете работать с перечислениями, с константами, с планами видов характеристик, если будете работать напрямую через SQL? Ну и самый веский аргумент - если когда нибудь решат закрыть базу или перейти на другую версию - весь импорт придется переписывать, т.к. 1С сформирует совсем другую структуру данных в SQL. Структура может будет и такой же, но все названия таблиц, названия полей будут другими. Да и 1С может быть не SQL-ной.
|
|
30.09.2008, 09:42 | #11 |
Участник
|
Всем спасибо за помощь, вроде разобрался.
Сделал несколько функций: 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(); |
|