Имя: Пароль:
1C
1С v8
передача параметров динамического списка в запрос
0 fvr2000
 
30.08.11
13:08
Здравствуйте!
Сталкнулся с такой задачей. Есть динамический список в форме списка регистра сведений. Регистр периодический с одним измерением - Сотрудник типа Справочник.ФизЛица и одним ресурсом - Количество, для хранения количества часов в графике работы сотрудника на конкретный день. В форме списка размещена кнопка "Заполнить", по нажатию которой необходимо заполнить табель на основании графика (типа с понедельника по пятницу по 8 часов, суббота-воскресенье выходные). Хочется, чтобы кнопка работала с учетом установленных пользователем отборов. Период передавать научился простым чтением параметров списка и передачей в запрос (Элементы.Список.Период.ДатаНачала, Элементы.Список.Период.ДатаОкончания). А вот как передать параметры отбора?
1 Rovan
 
гуру
30.08.11
13:20
//**************************************************************************
//  Получает ТЗ из списка-элемента формы со всеми отборами
Функция длПолучитьТаблицуЖурнала(СписокД) Экспорт
  ВидД = СтрЗаменить(Строка(СписокД.Значение), "Список", "");

  Если Лев(ВидД, 15) = "РегистрСведений" Тогда
      Если СписокД.ВыбиратьСрез = ИспользованиеСреза.Первые Тогда
          ВидД = ВидД + ".СрезПервых";
      ИначеЕсли СписокД.ВыбиратьСрез = ИспользованиеСреза.Последние Тогда
          ВидД = ВидД + ".СрезПоследних";
      КонецЕсли;
  КонецЕсли;

  ЗапросД = Новый Запрос;
  ТекстЗапроса = "Выбрать
      |   *
      |Из
      |   " + ВидД;
  _где = "
      |ГДЕ
      |   ";
  _и = "
      | И
      |   ";

  Попытка     //бывает, что Отбор недоступен (например при первом вызове и
      ОтборД = СписокД.Значение.Отбор;    //из проц. ПередОткрытием()
  Исключение
      ОтборД = Неопределено;
  КонецПопытки;

  БылоГде = Ложь;
  Если ОтборД <> Неопределено Тогда
      Для ИндексОтбора = 0 По ОтборД.Количество() - 1 Цикл
          Если ОтборД[ИндексОтбора].Использование Тогда
              Если не БылоГде Тогда
                  ТекстЗапроса = ТекстЗапроса + _где;
                  БылоГде = Истина;
              Иначе
                  ТекстЗапроса = ТекстЗапроса + _и;
              КонецЕсли;
              Вариант = 0;
              Если ОтборД[ИндексОтбора].ВидСравнения = ВидСравнения.Больше Тогда
                  ТекстЗапроса = ТекстЗапроса + ОтборД[ИндексОтбора].ПутьКДанным + " > ";
                  Вариант = 1;
              ИначеЕсли ОтборД[ИндексОтбора].ВидСравнения = ВидСравнения.БольшеИлиРавно Тогда
                  ТекстЗапроса = ТекстЗапроса + ОтборД[ИндексОтбора].ПутьКДанным +  " >= ";
                  Вариант = 1;
              ИначеЕсли ОтборД[ИндексОтбора].ВидСравнения = ВидСравнения.ВИерархии Тогда
                  ТекстЗапроса = ТекстЗапроса + ОтборД[ИндексОтбора].ПутьКДанным +  " В иерархии ";
                  Вариант = 4;
              ИначеЕсли ОтборД[ИндексОтбора].ВидСравнения = ВидСравнения.ВСписке Тогда
                  ТекстЗапроса = ТекстЗапроса + ОтборД[ИндексОтбора].ПутьКДанным +  " В ";
                  Вариант = 4;
              ИначеЕсли ОтборД[ИндексОтбора].ВидСравнения = ВидСравнения.ВСпискеПоИерархии Тогда
                  ТекстЗапроса = ТекстЗапроса + ОтборД[ИндексОтбора].ПутьКДанным +  " В иерархии ";
                  Вариант = 4;
              ИначеЕсли ОтборД[ИндексОтбора].ВидСравнения = ВидСравнения.Интервал Тогда
                  ТекстЗапроса = ТекстЗапроса + ОтборД[ИндексОтбора].ПутьКДанным +  " > &" + ОтборД[ИндексОтбора].ПутьКДанным + "1" + _и;
                  ТекстЗапроса = ТекстЗапроса + ОтборД[ИндексОтбора].ПутьКДанным +  " < &" + ОтборД[ИндексОтбора].ПутьКДанным + "2";
                  Вариант = 2;
              ИначеЕсли ОтборД[ИндексОтбора].ВидСравнения = ВидСравнения.ИнтервалВключаяГраницы Тогда
                  ТекстЗапроса = ТекстЗапроса + ОтборД[ИндексОтбора].ПутьКДанным +  " >= &" + ОтборД[ИндексОтбора].ПутьКДанным + "1" + _и;
                  ТекстЗапроса = ТекстЗапроса + ОтборД[ИндексОтбора].ПутьКДанным +  " <= &" + ОтборД[ИндексОтбора].ПутьКДанным + "2";
                  Вариант = 2;
              ИначеЕсли ОтборД[ИндексОтбора].ВидСравнения = ВидСравнения.ИнтервалВключаяНачало Тогда
                  ТекстЗапроса = ТекстЗапроса + ОтборД[ИндексОтбора].ПутьКДанным +  " >= &" + ОтборД[ИндексОтбора].ПутьКДанным + "1" + _и;
                  ТекстЗапроса = ТекстЗапроса + ОтборД[ИндексОтбора].ПутьКДанным +  " < &" + ОтборД[ИндексОтбора].ПутьКДанным + "2";
                  Вариант = 2;
              ИначеЕсли ОтборД[ИндексОтбора].ВидСравнения = ВидСравнения.ИнтервалВключаяОкончание Тогда
                  ТекстЗапроса = ТекстЗапроса + ОтборД[ИндексОтбора].ПутьКДанным +  " > &" + ОтборД[ИндексОтбора].ПутьКДанным + "1" + _и;
                  ТекстЗапроса = ТекстЗапроса + ОтборД[ИндексОтбора].ПутьКДанным +  " <= &" + ОтборД[ИндексОтбора].ПутьКДанным + "2";
                  Вариант = 2;
              ИначеЕсли ОтборД[ИндексОтбора].ВидСравнения = ВидСравнения.Меньше Тогда
                  ТекстЗапроса = ТекстЗапроса + ОтборД[ИндексОтбора].ПутьКДанным + " < ";
                  Вариант = 1;
              ИначеЕсли ОтборД[ИндексОтбора].ВидСравнения = ВидСравнения.МеньшеИлиРавно Тогда
                  ТекстЗапроса = ТекстЗапроса + ОтборД[ИндексОтбора].ПутьКДанным + " <= ";
                  Вариант = 1;
              ИначеЕсли ОтборД[ИндексОтбора].ВидСравнения = ВидСравнения.НеВИерархии Тогда
                  ТекстЗапроса = ТекстЗапроса + ОтборД[ИндексОтбора].ПутьКДанным +  " Не В иерархии ";
                  Вариант = 4;
              ИначеЕсли ОтборД[ИндексОтбора].ВидСравнения = ВидСравнения.НеВСписке Тогда
                  ТекстЗапроса = ТекстЗапроса + ОтборД[ИндексОтбора].ПутьКДанным +  " Не В ";
                  Вариант = 4;
              ИначеЕсли ОтборД[ИндексОтбора].ВидСравнения = ВидСравнения.НеВСпискеПоИерархии Тогда
                  ТекстЗапроса = ТекстЗапроса + ОтборД[ИндексОтбора].ПутьКДанным +  " Не В иерархии ";
                  Вариант = 4;
              ИначеЕсли ОтборД[ИндексОтбора].ВидСравнения = ВидСравнения.НеРавно Тогда
                  ТекстЗапроса = ТекстЗапроса + ОтборД[ИндексОтбора].ПутьКДанным + " <> ";
                  Вариант = 1;
              ИначеЕсли ОтборД[ИндексОтбора].ВидСравнения = ВидСравнения.Равно Тогда
                  ТекстЗапроса = ТекстЗапроса + ОтборД[ИндексОтбора].ПутьКДанным + " = ";
                  Вариант = 1;
              ИначеЕсли ОтборД[ИндексОтбора].ВидСравнения = ВидСравнения.Содержит Тогда
                  ТекстЗапроса = ТекстЗапроса + ОтборД[ИндексОтбора].ПутьКДанным + " Подобно ";
                  Вариант = 3;
              Иначе
                  Сообщить("Ошибка в функции длПолучитьТаблицуЖурнала() : обратитесь к разработчикам.");
              КонецЕсли;

              Если Вариант = 1 Тогда
                  ТекстЗапроса = ТекстЗапроса + "&" + ОтборД[ИндексОтбора].ПутьКДанным;
                  ЗапросД.УстановитьПараметр("" + ОтборД[ИндексОтбора].ПутьКДанным, ОтборД[ИндексОтбора].Значение);
              ИначеЕсли Вариант = 2 Тогда
                  ЗапросД.УстановитьПараметр("" + ОтборД[ИндексОтбора].ПутьКДанным + "1", ОтборД[ИндексОтбора].ЗначениеС);
                  ЗапросД.УстановитьПараметр("" + ОтборД[ИндексОтбора].ПутьКДанным + "2", ОтборД[ИндексОтбора].ЗначениеПо);
              ИначеЕсли Вариант = 3 Тогда
                  ТекстЗапроса = ТекстЗапроса + "&" + ОтборД[ИндексОтбора].ПутьКДанным;
                  ЗапросД.УстановитьПараметр("" + ОтборД[ИндексОтбора].ПутьКДанным, "%" + ОтборД[ИндексОтбора].Значение + "%");
              ИначеЕсли Вариант = 4 Тогда
                  ТекстЗапроса = ТекстЗапроса + "(&" + ОтборД[ИндексОтбора].ПутьКДанным + ")";
                  ЗапросД.УстановитьПараметр("" + ОтборД[ИндексОтбора].ПутьКДанным, ОтборД[ИндексОтбора].Значение);
              КонецЕсли;

          КонецЕсли;
      КонецЦикла;
  КонецЕсли;

  ЗапросД.Текст = ТекстЗапроса;

  тзТ = ЗапросД.Выполнить().Выгрузить();
  Возврат тзТ;
КонецФункции // ()
2 detec
 
30.08.11
13:21
(0) У динамического списка есть реквизит Отбор с типом ОтборКомпоновкиДанных.

В запрос их, боюсь, передать не получится. Я сталкивался с похожей ситуацией, реализовал через отчёт на СКД, куда в Конфигураторе интерактивно копирую текст запроса сложного динамического списка.
По идее, можно обойти элементы отбора и перенести их в отборы такого отчёта. Выполнить отчёт программно и получить на выходе таблицу значений.
3 fvr2000
 
30.08.11
13:27
(1) Спасибо, сейчас попробую, отпишусь.
(2) Вот-вот, как бы передать отбор программно? У меня сейчас простой запрос (Новый Запрос), а надо наверное на компоновке написать (Новый Построитель)? И потом, кнопка у меня &НаКлиенте, а передавать параметр надо &НаСервер
4 fvr2000
 
30.08.11
13:44
(1) Разместил код в модуле формы списка, попытался вызвать из обработчика кнопки, неуспешно:
{РегистрСведений.Табель.Форма.ФормаСписка.Форма(250)}: Ошибка при вызове метода контекста (длПолучитьТаблицуЖурнала)
   ЗапросД = длПолучитьТаблицуЖурнала(Элементы.Список);
по причине:
Ошибка передачи данных между клиентом и сервером. Значение недопустимого типа.
по причине:
Ошибка преобразования данных XDTO:
Запись значения свойства 'param':
   форма: Элемент
   имя: {http://v8.1c.ru/8.2/managed-application/modules}param
по причине:
Ошибка отображения типов:
Отсутствует отображение для типа 'ТаблицаФормы'
5 fvr2000
 
30.08.11
14:27
(1) Обошелся вот таким способом

ЗаполнитьТабельНаСервере(Элементы.Список.Период.ДатаНачала, Элементы.Список.Период.ДатаОкончания, ?(Список.Отбор.Элементы.Количество() = 0, NULL, Список.Отбор.Элементы[0].ПравоеЗначение));

Работать будет не всегда, но пока хватит. Однако, хотелось бы найти более универсальное решение, с передачей отбора на сервер.
6 detec
 
30.08.11
14:34
(5) Вообще-то отбор компоновки данных сериализуется, и нет никаких проблем в сериализованном виде гонять его между клиентом и сервером.

&НаСервере
Функция ВосстановитьОбъектXDTO(СтрокаXML) Экспорт
   
   ЧтениеXML = Новый ЧтениеXML;
   ЧтениеXML.УстановитьСтроку(СтрокаXML);
   Попытка
       Объект = СериализаторXDTO.ПрочитатьXML(ЧтениеXML);
       
   Исключение
       Объект = Неопределено;
   КонецПопытки;    
   ЧтениеXML.Закрыть();
   Возврат Объект;
   
КонецФункции

&НаСервере
Функция СериализоватьОбъектXDTO(Объект) Экспорт
   
   ЗаписьXML = Новый ЗаписьXML();
   ЗаписьXML.УстановитьСтроку();
   
   СериализаторXDTO.ЗаписатьXML(ЗаписьXML, Объект, НазначениеТипаXML.Явное);
       
   СтрокаXML = ЗаписьXML.Закрыть();
   Возврат СтрокаXML;
   
КонецФункции
7 fvr2000
 
30.08.11
15:48
(5) С этого места поподробнее, плз :)
Направление в принципе понятно. Однако целиком загрузить отбор для набора записей регистра сведений (или для построителя запроса) не получится (свойство Отбор только чтение), а как коллекцию элементов загрузить из сериализованного представления?