Взаимодействие через OLE ч.2 - Общие вопросы по 1С 7.7 - 1С v.7.7 - Каталог статей - Программирование в 1С
Программирование в 1СВоскресенье, 04.12.2016, 01:48

| RSS
Главная | Каталог статей
Меню сайта

Категории раздела
Основы [36]
Общие вопросы по 1С 7.7 [88]
1С: Бухгалтерия 7.7 [7]
1С: Торговля 7.7 [4]
1С:Зарплата и кадры 7.7 [1]
1С 7.7: Проблемы и решения [33]
УРБД [3]
Управление Распределенными Базами Данных
OLE [2]
Механизм обмена данными между базами 1С через OLE
SQL [1]
Сервер терминалов [1]
Интеграция с внешними приложениями [3]
FAQ по 1С v.7.7 [7]
FAQ по 1С v.7.7

Поиск

Поиск по сайту

Главная » Статьи » 1С v.7.7 » Общие вопросы по 1С 7.7

Взаимодействие через OLE ч.2
Начало...

Вначале допишем в глобальном модуле базы OLE немного строк, которые нам помогут в работе:
 
//**************************************************************
Перем СписокЗначенийЗапроса[10] Экспорт; // Мы в них "запихнем" значения для запроса
//**************************************************************
Функция СкорректироватьСписок(ИндексМассива
          Действие
          ТипОбъекта = "", 
          ВидОбъекта = "", 
          Параметр1 = "", 
          Параметр2 = "", 
          Параметр3 = "",
// Ну и далее по параметрам, сколько надо 
          // …………………
 
          Параметр99 = "") Экспорт

ИндексМассива=Число(ИндексМассива);
Если ИндексМассива = 0 Тогда
     Возврат -99; // Ошибка: Не указали индекс массива ?
КонецЕсли;
Если Действие = 1 Тогда // Очистить список значений
СписокЗначенийЗапроса[ИндексМассива].УдалитьВсе();
     Возврат 1;
ИначеЕсли Действие = 2 Тогда // Добавить объект в список 
     Если ТипОбъекта = "Документ" Тогда 
          Если ВидОбъекта = "" Тогда 
               Возврат -99; // Ошибка: Передавайте нормальный вид объекта! 
          КонецЕсли
          Попытка 
               Док = СоздатьОбъект("Документ."+ВидОбъекта); 
          Исключение 
               Возврат -99; // Ошибка: Попытка обращения к неверному объекту 
          КонецПопытки
          Если Док.НайтиПоНомеру(Параметр1,Параметр2)=1 Тогда 
               СписокЗначенийЗапроса[ИндексМассива].ДобавитьЗначение(Док.ТекущийДокумент()); 
               Возврат 1; // Нашли документ 
          Иначе 
               Возврат 0; // Не нашли документ :( 
          КонецЕсли
     ИначеЕсли ТипОбъекта = "Справочник" Тогда 
          Если ВидОбъекта = "" Тогда 
               Возврат -99; // Ошибка: Передавайте нормальный вид объекта! 
          КонецЕсли
          Попытка 
               Спр = СоздатьОбъект("Справочник."+ВидОбъекта); 
          Исключение 
               Возврат -99; // Ошибка: Попытка обращения к неверному объекту 
          КонецПопытки
         
// Параметр1 - Код 
          // Параметр2 - наименование 
          // Параметр3 - флаг глобального поиска
 
          Если Спр.НайтиПоКоду(Параметр1,Число(Параметр3))=1 Тогда 
               СписокЗначенийЗапроса[ИндексМассива].ДобавитьЗначение(Спр.ТекущийЭлемент()); 
               Возврат 1; // Нашли элемент 
          ИначеЕсли Спр.НайтиПоНаименованию(Параметр2,Число(Параметр3))=1 Тогда 
               СписокЗначенийЗапроса[ИндексМассива].ДобавитьЗначение(Спр.ТекущийЭлемент()); 
               Возврат 1; // Нашли элемент 
          Иначе 
               Возврат 0; // Не нашли элемент :( 
          КонецЕсли
     ИначеЕсли ТипОбъекта = "Счет" Тогда 
         
// Вид объекта - Идентификатор плана счетов 
          // Параметр1 - Код счета
 
          Попытка 
               Если ВидОбъекта<>"" Тогда 
                    ИскомыйСчет = СчетПоКоду(Параметр1, ПланСчетов.ЗначениеПоИдентификатору(ВидОбъекта)); 
               Иначе
                    ИскомыйСчет = СчетПоКоду(Параметр1); 
               КонецЕсли
               Если ПустоеЗначение(ИскомыйСчет) = 1 Тогда 
                    Возврат 0; // не нашли счет :( 
               Иначе
                    СписокЗначенийЗапроса[ИндексМассива].ДобавитьЗначение(ИскомыйСчет); 
                    Возврат 1; // нашли счет 
               КонецЕсли
          Исключение 
               Возврат -99; // Ошибка: Неверный тип объекта 
          КонецПопытки
     ИначеЕсли Действие = 3 Тогда // Вернуть размер списка 
          Возврат СписокЗначенийЗапроса[ИндексМассива].РазмерСписка(); 
     Иначе 
          Возврат -99; // Ошибка: Неверное действие 
     КонецЕсли
     Возврат -999; // ??? 
КонецЕсли;
КонецФункции

//**************************************************************
Процедура ПриНачалеРаботыСистемы()
// Данная процедура уже есть в глобальном модуле, просто надо
// дописать в ней несколько строк:

Для Сч=1 По 10 Цикл 
     СписокЗначенийЗапроса[Сч]=СоздатьОбъект("СписокЗначений");
КонецЦикла;
КонецПроцедуры
//**************************************************************

Теперь начинаем потихоньку писать сам запрос. Что мы имеем:
В форме диалога местной базы несколько реквизитов диалога (либо местные переменные):
  • Даты периода (НачДата и КонДата)
  • Элементы справочников для фильтрации (ВыбТовар, ВыбФирма, ВыбКлиент, и т.д.)
  • Какие-либо флажки (ТолькоЗамерзающийЗимойТовар , ..)
Мы начинаем писать запрос и сразу попадаем в такую ловушку:
 
ТекстЗапроса = " Период с НачДата по КонДата; ";

Вроде все в порядке, но такой запрос не выполнится в базе OLE, так как там понятия не имеют, что такое НачДата и КонДата :)) Ведь эти переменные действительны только для местной базы! Переписываем запрос заново:
 
ТекстЗапроса = " Период с '" + НачДата + "' по '" + КонДата + "';
// Будет типа '01.01.02'
// т.е. прямое представление даты, которое всегда поймет любой запрос

| Товар = Регистр.ОстаткиТоваров.Товар;
| Фирма = Регистр.ОстаткиТоваров.Фирма;
| Склад = Регистр.ОстаткиТоваров.Склад;
| Остаток = Регистр.ОстаткиТоваров.Остаток;
| Группировка Товар без групп;
| Группировка Документ;
| Функция НачОст = НачОст(Остаток);
| Функция КонОст = КонОст(Остаток);
| Функция ПрихОст = Приход(Остаток);
| Функция РасхОст = Расход(Остаток);";

Так... Дошли до условий отбора в запросе. Рассмотрим два варианта, когда выбран ВыбТовар:
 
// 1-й вариант - когда выбран элемент справочника (не группа).
// Самый простой случай - коды товаров совпадают абсолютно
// Вариант 1а.

Если ВыбТовар.Выбран()=1 Тогда
     ТекстЗапроса = ТекстЗапроса +
     | Условие (Товар.Код = " +ВыбТовар.Код+");";
КонецЕсли;
// Вариант 1б. Чтоб запрос быстрее был:
// Вначале добавим к запросу переменную в общем списке:
 
     | КодТовара = Регистр.ОстаткиТоваров.Товар.Код;
// А уж потом добавим к запросу условие (такое условие будет выполнятся проще, так как
// запрос при формировании таблицы запроса сразу сформирует отдельную колонку кодов и по
// ней уже будет отбирать, а не будет каждый раз при обработке товаров извлекать из них
// код):

Если ВыбТовар.Выбран()=1 Тогда 
     ТекстЗапроса = ТекстЗапроса +
     | Условие (КодТовара = " +ВыбТовар.Код+");";
КонецЕсли;

Казалось бы все очень просто. По аналогии - если уникальность для товаров ведется по наименованию, то простой заменой слова "код" на "наименование" мы решаем вопрос и здесь. Теперь рассмотрим, когда мы выбрали группу, т.е. текст условия должен будет выглядеть так:
 
| Условие (Товар.ПринадлежитГруппе(КакаяТоГруппа)=1);

И здесь, правда можно проблему решить "двумями путями" :)) Первый пусть - когда мы имеем дело с двухуровне вымсправочником. Тогда проблема группы решается также просто, как и в 1-м варианте:
 
// Добавляем в списке переменных строку:
     | КодРодителя = Регистр.ОстаткиТоваров.Товар.Родитель.Код;
// Далее пишем условие:
Если ВыбТовар.Выбран()=1 Тогда 
     ТекстЗапроса = ТекстЗапроса +
     | Условие (КодРодителя = " +ВыбТовар.Код+");";
КонецЕсли;
// В качестве домашнего задания - переписать условие по наименоваиню :)))

А если справочник очень даже многоуровневый? Вот для этого мы и используем написанную ранее функцию. Предположим, что список значений запроса с индексом массива " 1 " мы будем использовать для хранения подобных значений (например, хранить в нем группы товаров, клиентов) для хитрых условий. Итак, например, в ВыбТовар у нас указана группа товаров, а в ВыбКлиент - группа клиентов, которым мы товары группы ВыбТовар продавали. Кроме того, мы должны пропустить накладные возвратов поставщикам, и не забыть, что товары надо еще отбирать по флажку ТолькоЗамерзающийЗимойТовар:
 
// Очистим список значений запроса
Результат = БазаОле.EvalExpr("СкорректироватьСписок(1,1)");
// Закинем в список значений запроса группу товаров (он сам найдет ее в базе OLE)
// И запоминаем (в уме), что этой группе соответствует 1-е значение списка

Результат = БазаОле.EvalExpr("СкорректироватьСписок(1, 2 , ""Справочник"", """  +
     ВыбТовар.Вид())+ """," + ВыбТовар.Код + ", """ +
     ВыбТовар.Наименование + """)");
// Теперь закинем в список значений запроса группу клиентов
// И запоминаем, что этой группе соответствует 2-е значение списка

Результат = БазаОле.EvalExpr("СкорректироватьСписок(1, 2 , ""Справочник"", """  +
     ВыбКлиент.Вид())+ """," + ВыбКлиент.Код + ", """ + 
     ВыбКлиент.Наименование + """)");
// А еще до кучи и фирму из ВыбФирма
// И запоминаем, что этой фирме соответствует 3-е значение списка

Результат = БазаОле.EvalExpr("СкорректироватьСписок(1, 2 , ""Справочник"", """  +
     ВыбФирма.Вид())+ """," + ВыбФирма.Код + ", """ + 
     ВыбФирма.Наименование + """)");
// Теперь формируем текст запроса
ТекстЗапроса = " Период с '"+НачДата+ "' по '"+КонДата+"'; 
     | Товар = Документ.РасходнаяНакладная.Товар; 
     | Замерзает = Документ.РасходнаяНакладная.Товар.ЗамерзаетЗимой; 
     | Признак = Документ.РасходнаяНакладная.ПризнакНакладной; 
     | Фирма = Документ.РасходнаяНакладная.Фирма; 
     | Клиент = Документ.РасходнаяНакладная.Клиент; 
     | Количество = Документ.РасходнаяНакладная.Количество; 
     | СуммаДок = Документ.РасходнаяНакладная.Сумма; 
     | Группировка Товар без групп; 
     | Группировка Документ; 
     | Функция СуммаОтгрузки=Сумма(СуммаДок); 
     | Условие (Признак<>Перечисление.ПризнРасхНакл.ВозвратПоставщику); 
     | Условие (Замерзает = " + ТолькоЗамерзающийЗимойТовар + "); 
     // Внимание! Начинается: 
     | Условие (Товар.ПринадлежитГруппе(СписокЗначенийЗапроса[1].ПолучитьЗначение(1))=1); 
     | Условие (Клиент.ПринадлежитГруппе(СписокЗначенийЗапроса[1].ПолучитьЗначение(2))=1); 
     | Условие (Фирма= СписокЗначенийЗапроса[1].ПолучитьЗначение(3));";

Уфф. Вроде все… Остается только запустить запрос:
  
Запрос = БазаОле.CreateObject("Запрос");
Если Запрос.Выполнить(ТекстЗапроса)=0 Тогда
     Предупреждение("Запрос безутешен!");
     Возврат;
КонецЕсли;

Ну, а с реквизитами запроса разбираемся так же, как указано было выше в предыдущих разделах… И не забываем, что кроме хранения конкретных значений, можно использовать другие списки значений запроса. Например, можно заполнить какой-либо список значений запроса списком клиентов и использовать его в запросе:

// Всякими правдами/неправдами заполнили список значений (хотя бы через другой запрос :))
// конкретными клиентами…
// Предположим, индекс массива равен "2". Тогда в тексте запроса появится следующее:

     | Условие (Клиенты в СписокЗначенийЗапроса[2]);

P.S. Чего еще нет: перенос реквизитов неограниченной длины, более подробно остановиться на "периодических реквихитах"…

ГРОМАДНЕЙШИЕ ИЗВИНЕНИЯ ЗА ВОЗМОЖНЫЕ СИНТАКСИЧЕСКИЕ И ОРФОГРАФИЧЕСКИЕ ОШИБКИ В ДОКУМЕНТЕ - ПИСАЛ БЕЗ ПРОВЕРКИ В 1С, БОЛЬШУЮ ЧАСТЬ - ПО ПАМЯТИ. ЕСЛИ ОБНАРУЖИТЕ ОШИБКИ, ДА И ВООБЩЕ, ЕСЛИ ЕСТЬ ВОПРОСЫ ПО OLE - ПИШИТЕ. ЕСЛИ ВЫКРОЮ ВРЕМЯ, ТО ПОИЩУ РЕШЕНИЕ…

С наилучшими пожеланиями,
Руководитель информационно-технического отдела ООО МФФ "Аконит"
Егоров Андрей Викторович
Категория: Общие вопросы по 1С 7.7 | Добавил: Spacer (06.10.2009)
Просмотров: 4540
Всего комментариев: 0
Добавлять комментарии могут только зарегистрированные пользователи.
[ Регистрация | Вход ]
Друзья сайта
  • Официальный блог
  • Сообщество uCoz
  • FAQ по системе
  • Инструкции для uCoz

  • Статистика

    Copyright 1C:Programmer © 2016
    Бесплатный конструктор сайтов - uCoz