При разработке отчетов или обработок в среде 1С:Предприятие 8 часто возникает задача предоставить пользователю возможность выбора нескольких элементов из справочника. Классический пример — фильтрация данных по нескольким отделам, складам или контрагентам. Для реализации такого механизма удобнее всего использовать объект СписокЗначений. Рассмотрим подробно, как правильно заполнить этот список данными из базы, как организовать интерактивный выбор и избежать распространенных ошибок начинающих разработчиков.
Первым делом нам необходимо получить список всех элементов справочника. Наиболее эффективным способом извлечения данных в 1С является использование механизма запросов. Рассмотрим ситуацию на примере справочника Отделы. Проанализируем, как получить данные на сервере и передать их в список значений.
Многие начинающие программисты пытаются использовать в фильтрах наименования (строки), однако правильным подходом является использование ссылок. Ссылки обеспечивают уникальность данных и корректную работу фильтров в запросах, даже если два отдела называются одинаково.
Разберем пример кода для заполнения списка значений на сервере:
&НаСервере
Процедура ЗаполнитьСписокОтделовНаСервере()
// Создаем новый запрос к базе данных
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Отделы.Ссылка КАК Ссылка
|ИЗ
| Справочник.Отделы КАК Отделы
|ГДЕ
| НЕ Отделы.ПометкаУдаления
|УПОРЯДОЧИТЬ ПО
| Отделы.Наименование";
// Выполняем запрос и выгружаем результат в колонку массива
РезультатЗапроса = Запрос.Выполнить();
МассивСсылок = РезультатЗапроса.Выгрузить().ВыгрузитьКолонку("Ссылка");
// Загружаем полученный массив в СписокЗначений, который находится на форме
СписокОтделовНаФорме.ЗагрузитьЗначения(МассивСсылок);
КонецПроцедуры
Обратите внимание на использование метода ЗагрузитьЗначения(). Это очень быстрый способ заполнить СписокЗначений данными из массива без использования циклов. Мы также добавили условие НЕ Отделы.ПометкаУдаления, чтобы не предлагать пользователю выбирать неактуальные (удаленные) подразделения.
После того как мы подготовили список всех доступных отделов, нам нужно предоставить пользователю возможность отметить нужные. Для этого в 1С существует стандартный метод ОтметитьЭлементы(). Проанализируем, как правильно вызвать это окно и обработать результат выбора.
Важно помнить, что в управляемом приложении работа с диалоговыми окнами имеет свои особенности. Рассмотрим клиентскую процедуру:
&НаКлиенте
Процедура КомандаВыбратьОтделы(Команда)
// Вызываем стандартное окно со списком флажков
ОписаниеОповещения = Новый ОписаниеОповещения("ПослеВыбораОтделов", ЭтотОбъект);
СписокОтделовНаФорме.ПоказатьОтметкуЭлементов(ОписаниеОповещения, "Выберите отделы для отчета");
КонецПроцедуры
&НаКлиенте
Процедура ПослеВыбораОтделов(Результат, ДополнительныеПараметры) Экспорт
Если Результат = Неопределено Тогда
// Пользователь нажал "Отмена"
Возврат;
КонецЕсли;
// Теперь мы можем перебрать список и посмотреть, какие элементы отмечены
Для Каждого ЭлементСписка Из СписокОтделовНаФорме Цикл
Если ЭлементСписка.Пометка Тогда
// Элемент выбран пользователем
Сообщить("Выбран отдел: " + ЭлементСписка.Значение);
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Важный нюанс: часто возникает ошибка Поле объекта не обнаружено (Пометка). Это случается, если разработчик пытается обратиться к свойству Пометка у самого объекта СписокЗначений вместо того, чтобы обращаться к конкретному ЭлементСпискаЗначений внутри цикла. Выясним причину: СписокЗначений — это коллекция, а Пометка — это свойство каждого отдельного элемента этой коллекции.
Когда пользователь выбрал необходимые отделы, нам нужно передать этот список в параметры запроса, который формирует отчет. Рассмотрим, как это сделать правильно:
&НаСервере
Процедура СформироватьОтчетНаСервере()
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Продажи.СуммаОборот КАК Сумма
|ИЗ
| РегистрНакопления.Продажи.Обороты(,, Авто, Отдел В (&СписокОтделов)) КАК Продажи";
// Создаем массив из помеченных элементов для передачи в параметр
ВыбранныеОтделы = СписокОтделовНаФорме.ВыгрузитьЗначения(); // Можно выгрузить только помеченные вручную
// Или более точный способ:
МассивДляПараметра = Новый Массив;
Для Каждого Элемент Из СписокОтделовНаФорме Цикл
Если Элемент.Пометка Тогда
МассивДляПараметра.Добавить(Элемент.Значение);
КонецЕсли;
КонецЦикла;
Запрос.УстановитьПараметр("СписокОтделов", МассивДляПараметра);
// Дальнейшая логика выполнения запроса...
КонецПроцедуры
Использование оператора В (&Параметр) в языке запросов 1С позволяет эффективно фильтровать данные по массиву или списку значений. Платформа автоматически преобразует это в SQL-инструкцию IN (...).
Проанализируем ситуацию, описанную в сообщениях форума, когда возникает ошибка Ошибка отображения типов: Отсутствует отображение для типа 'ЭлементСпискаЗначений'. Это одна из самых коварных ошибок при работе с управляемыми формами.
Причина ошибки: Объект СписокЗначений может быть передан с клиента на сервер, так как он сериализуется. Однако отдельный объект ЭлементСпискаЗначений (который вы получаете в цикле Для Каждого) не может быть передан через границу "клиент-сервер".
Если вы попытаетесь передать элемент списка в серверную процедуру как параметр, система выдаст ошибку. Чтобы этого избежать:
ЭлементСпискаЗначений в параметры серверных процедур.СписокЗначений, либо массив "чистых" значений (ссылок, строк, чисел), извлеченных из списка.Если ваша задача — создать полноценный отчет, рассмотрим самый профессиональный путь. В Системе Компоновки Данных (СКД) вам не нужно писать код для заполнения списков и обработки пометок. Достаточно выполнить следующие действия:
Отдел).СправочникСсылка.Отделы.В этом случае платформа 1С самостоятельно сформирует удобный интерфейс для выбора нескольких элементов, включая поиск, подбор и иерархию, что избавит вас от написания лишнего кода и потенциальных ошибок.
Подводя итог, можно сказать, что ручное заполнение СпискаЗначений через Запрос — отличный метод для кастомных обработок, но всегда стоит помнить о правилах взаимодействия клиента и сервера и отдавать предпочтение ссылкам перед наименованиями.