Как получить данные из списка регистра с учетом пользовательских отборов и избежать ошибок Построителя Запроса

Программист 1С v8.3 (Обычные формы) IT и автоматизация бизнеса
← На главную

В процессе разработки на платформе «1С:Предприятие» (особенно при работе с обычными формами) часто возникает задача: получить во временную таблицу или таблицу значений именно те данные из формы списка, которые пользователь видит на экране в данный момент — то есть с учетом всех интерактивно установленных отборов, сортировок и группировок. Для решения этой задачи традиционно применяется объект ПостроительЗапроса.

Однако при попытке программно настроить или скопировать отборы разработчики часто сталкиваются с неприятной ошибкой: «Ошибка при вызове метода контекста (Добавить): Недопустимое значение параметра (параметр номер '1')». В этой статье мы подробно разберем, почему возникает эта ошибка, как работает механизм автоматического переноса отборов платформой 1С и как правильно писать код, чтобы избежать лишних циклов и повысить производительность системы.

Анализ ошибки: почему ручное добавление отборов приводит к сбою?

Рассмотрим исходный фрагмент кода, который часто пишут начинающие разработчики:


ПостроительЗапроса = Новый ПостроительЗапроса; 
ПостроительЗапроса.ИсточникДанных = Новый ОписаниеИсточникаДанных(РегистрСведенийСписок); 

Для Каждого ЭлементОтбора Из Отбор Цикл 
    Если ЭлементОтбора.Использование Тогда 
        НовыйОтбор = ПостроительЗапроса.Отбор.Добавить(ЭлементОтбора.Имя); // Ошибка здесь!
        НовыйОтбор.Использование = Истина; 
        НовыйОтбор.ВидСравнения = ЭлементОтбора.ВидСравнения; 
        НовыйОтбор.Значение = ЭлементОтбора.Значение; 
    КонецЕсли; 
КонецЦикла; 

Попытка вызвать метод Добавить у коллекции ПостроительЗапроса.Отбор с передачей туда имени элемента отбора формы приводит к исключению. Выясним причину этого поведения:

  1. Отсутствие поля в доступных полях построителя. Метод Добавить() первым параметром принимает путь к данным (имя поля), по которому будет производиться отбор. Этот путь к данным обязательно должен присутствовать в коллекции ПостроительЗапроса.ДоступныеПоля. Если построитель запроса еще не инициализировал структуру источника данных или структура не совпадает, метод вернет ошибку недопустимого параметра.
  2. Несовпадение имен полей. Имя элемента отбора на форме (например, в табличном поле) далеко не всегда совпадает с реальным физическим именем поля в таблице базы данных или в метаданных. На форме могут присутствовать связанные поля, реквизиты через точку или виртуальные колонки, которые построитель запроса напрямую обработать не может без предварительного анализа.
  3. Пропущенный шаг инициализации настроек. Даже если имя поля верное, без вызова метода ПостроительЗапроса.ЗаполнитьНастройки() коллекция доступных полей отбора может оставаться пустой, из-за чего платформа отвергает любые попытки программного добавления элементов.

Элегантное решение: используем встроенные возможности платформы

Самая главная и приятная новость заключается в том, что ручной перебор элементов отбора в цикле вообще не нужен! Разработчики платформы «1С:Предприятие» заранее заложили этот сценарий в логику работы системы.

Когда мы инициализируем объект ОписаниеИсточникаДанных и передаем в него объект списка (например, РегистрСведенийСписок, СправочникСписок или ДокументСписок), происходит автоматическая магия: платформа самостоятельно считывает все настройки отображения этого списка из формы. Это включает в себя:

Таким образом, объект ОписаниеИсточникаДанных уже содержит в себе готовую схему фильтрации. Нам не нужно обходить коллекцию Отбор и вручную сопоставлять виды сравнения и значения.

Давайте посмотрим на пример правильного, лаконичного и быстрого кода, который решает задачу автора в три строки:


// 1. Инициализируем построитель запроса
ПостроительЗапроса = Новый ПостроительЗапроса; 

// 2. Указываем источник данных, передавая туда список из формы.
// Платформа автоматически применит к источнику все текущие отборы формы!
ПостроительЗапроса.ИсточникДанных = Новый ОписаниеИсточникаДанных(РегистрСведенийСписок); 

// 3. Выполняем запрос и выгружаем результат в Таблицу Значений
ПостроительЗапроса.Выполнить();
ТаблицаРезультат = ПостроительЗапроса.Результат.Выгрузить();

Этот код абсолютно безопасен, не подвержен ошибкам несовпадения типов данных и работает значительно быстрее, поскольку все операции по наложению фильтров выполняются на уровне платформы в оптимизированном скомпилированном коде.

Что делать, если нужно наложить дополнительные программные отборы?

Иногда возникает обратная ситуация: вам нужно взять отборы пользователя из формы списка, но при этом программно добавить к ним еще один жесткий критерий фильтрации, который пользователь не должен видеть или иметь возможность отключить. В таком случае алгоритм действий будет следующим:

  1. Сначала связываем построитель с источником данных формы, чтобы получить базовые пользовательские фильтры.
  2. Вызываем метод ЗаполнитьНастройки(), чтобы зафиксировать структуру полей.
  3. Программно обращаемся к конкретному полю в коллекции ПостроительЗапроса.Отбор. Если поле существует в доступных полях, мы просто включаем его использование и задаем значение.

Разберем практический пример реализации такого сценария:


ПостроительЗапроса = Новый ПостроительЗапроса; 
ПостроительЗапроса.ИсточникДанных = Новый ОписаниеИсточникаДанных(РегистрСведенийСписок); 

// Заполняем доступные поля на основе источника данных
ПостроительЗапроса.ЗаполнитьНастройки();

// Добавляем или модифицируем отбор по конкретному полю, например, "Организация"
ИмяПоляОтбора = "Организация";
ЭлементОтбора = ПостроительЗапроса.Отбор.Найти(ИмяПоляОтбора);

Если ЭлементОтбора <> Неопределено Тогда
    ЭлементОтбора.Использование = Истина;
    ЭлементОтбора.ВидСравнения  = ВидСравнения.Равно;
    ЭлементОтбора.Значение      = СсылкаНаНужнуюОрганизацию;
Иначе
    // Если поле не найдено напрямую в отборах, его можно попробовать добавить
    НовыйОтбор = ПостроительЗапроса.Отбор.Добавить(ИмяПоляОтбора);
    НовыйОтбор.Использование = Истина;
    НовыйОтбор.ВидСравнения  = ВидСравнения.Равно;
    НовыйОтбор.Значение      = СсылкаНаНужнуюОрганизацию;
КонецЕсли;

ПостроительЗапроса.Выполнить();
РезультатТаблица = ПостроительЗапроса.Result.Unload(); // Получаем итоговую таблицу данных

Современная альтернатива: как решать эту задачу в Управляемых формах (1С 8.3)

Объекты типа РегистрСведенийСписок и ПостроительЗапроса — это наследие обычного интерфейса (толстого клиента 1С 8.1 / 8.2). В современных конфигурациях на управляемых формах (интерфейс «Такси») используется совершенно другой подход.

Для отображения списков в управляемом интерфейсе применяется объект ДинамическийСписок. Напрямую использовать ПостроительЗапроса для получения данных из динамического списка невозможно. Вместо этого разработчики используют механизмы Системы компоновки данных (СКД).

Проанализируем пример схемы получения данных из динамического списка управляемой формы на сервере:


// Получаем схему компоновки и настройки динамического списка
Схема = Элементы.Список.ПолучитьИсполняемуюСхемуКомпоновкиДанных();
Настройки = Элементы.Список.ПолучитьИсполняемыеНастройкиКомпоновкиДанных();

// Инициализируем компоновщик макета
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
МакетКомпоновки = КомпоновщикМакета.Выполнить(Схема, Настройки,,, Тип("ГенераторМакетаКомпоновкиДанныхДляКоллекцииЗначений"));

// Проводим компоновку данных
ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновки.Инициализировать(МакетКомпоновки);

// Выводим результат в таблицу значений
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВКоллекциюЗначений;
ТаблицаРезультат = Новый ТаблицаЗначений;
ПроцессорВывода.УстановитьОбъект(ТаблицаРезультат);
ПроцессорВывода.Вывести(ПроцессорКомпоновки);

// В переменной ТаблицаРезультат теперь находятся отфильтрованные данные списка

Этот способ является стандартом разработки под управляемое приложение 1С 8.3. Он гарантирует корректный учет всех пользовательских настроек, включая сложные условные оформления, группировки и динамические отборы, установленные через свойства «Настройка списка».

Выводы и рекомендации

Подводя итог нашему разбору, выделим несколько ключевых правил для работы с отборами в 1С:

← На главную