Как реализовать выбор и хранение нескольких элементов справочника в настройках пользователя 1С?

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

При разработке функционала в конфигурациях на базе обычных форм (например, Управление производственным предприятием 1.2/1.3) разработчики часто сталкиваются с ограничением стандартного механизма настроек пользователей. Стандартный ПланВидовХарактеристик.НастройкиПользователей ориентирован на хранение одиночных (скалярных) значений: одной ссылки, одной строки, одного числа или даты. Попытка выбрать несколько элементов в форме выбора справочника приводит к тому, что кнопка «Выбрать» становится неактивной, так как целевой реквизит не предназначен для коллекции данных.

Рассмотрим подробнее, почему так происходит, и разберем несколько эффективных способов решения этой задачи, от простых архитектурных изменений до программных методов сериализации.

Почему не работает множественный выбор в стандартной настройке?

Выясним причину поведения системы. Когда мы открываем форму выбора справочника из поля, связанного с настройкой пользователя, платформа анализирует тип значения этой настройки. Если в Плане видов характеристик (ПВХ) для данной настройки указан тип СправочникСсылка, платформа ожидает получить ровно один элемент. Включение режима МножественныйВыбор = Истина в форме справочника позволяет выделить несколько строк, но штатный механизм возврата значения не понимает, как «упаковать» этот массив в одиночную ячейку. В итоге кнопка выбора блокируется, предотвращая ошибку несоответствия типов.

Для реализации хранения списка значений нам придется выйти за рамки стандартного поведения. Рассмотрим основные пути решения.

Решение 1: Использование специализированного регистра сведений

Проанализируем этот вариант как наиболее правильный с точки зрения архитектуры 1С. Вместо того чтобы пытаться «впихнуть» массив данных в одну строку настроек, мы создадим структуру, предназначенную для хранения связей «много-ко-многим».

Разберем по шагам создание такого механизма:

  1. Создадим новый РегистрСведений (например, ДополнительныеНастройкиПользователей).
  2. В измерениях укажем Пользователь (тип СправочникСсылка.Пользователи) и Настройка (тип ПланВидовХарактеристикСсылка.НастройкиПользователей).
  3. Добавим третье измерение — Значение (тип СправочникСсылка нужного вам справочника).

Такая структура позволяет хранить для одного пользователя и одной настройки произвольное количество записей. Проанализируем пример кода для получения этих данных в запросе:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |	ДопНастройки.Значение КАК Значение
    |ИЗ
    |	РегистрСведений.ДополнительныеНастройкиПользователей КАК ДопНастройки
    |ГДЕ
    |	ДопНастройки.Пользователь = &ТекущийПользователь
    |	И ДопНастройки.Настройка = &НужнаяНастройка";

Запрос.УстановитьПараметр("ТекущийПользователь", ПараметрыСеанса.ТекущийПользователь);
Запрос.УстановитьПараметр("НужнаяНастройка", ПланыВидовХарактеристик.НастройкиПользователей.МояМножественнаяНастройка);

СписокВыбранныхЭлементов = Запрос.Выполнить().Выгрузить().ВыгрузитьКолонку("Значение");

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

Решение 2: Расширение типов Плана видов характеристик

Если вы все же хотите использовать стандартную форму «Настройки пользователя», можно изменить состав доступных типов в самом ПВХ. Посмотрим, как это реализовать:

В конфигураторе найдите ПланВидовХарактеристик.НастройкиПользователей. В свойстве «Тип значения характеристик» нужно добавить тип СписокЗначений. После этого для вашей настройки можно будет выбрать этот тип.

Однако здесь есть нюанс. Стандартная форма редактирования настроек в УПП может не иметь встроенного визуального редактора для типа СписокЗначений. Вам может потребоваться доработка формы, чтобы при нажатии на кнопку выбора открывалось окно редактирования списка значений, а не просто форма справочника.

Рассмотрим пример программного вызова подбора элементов в СписокЗначений:


// В обработчике нажатия кнопки выбора в форме настроек
ФормаВыбора = Справочники.Номенклатура.ПолучитьФормуВыбора(, ЭтаФорма);
ФормаВыбора.МножественныйВыбор = Истина;
ВыбранныеДанные = ФормаВыбора.ОткрытьМодально();

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

Решение 3: Сериализация коллекции в строку (XML или JSON)

В случаях, когда менять структуру метаданных (добавлять регистры) нельзя, а тип настройки жестко ограничен строкой, можно использовать метод «упаковки» данных. Проанализируем ситуацию: использование кодов через запятую (например, "001,005,010") крайне не рекомендуется, так как это усложняет поиск и может привести к ошибкам при изменении кодов справочника.

Лучше использовать стандартную сериализацию 1С. Разберем пример, как преобразовать СписокЗначений в строку XML и обратно:


// Сериализация (сохранение в строку)
СписокДляСохранения = Новый СписокЗначений;
СписокДляСохранения.Добавить(Ссылка1);
СписокДляСохранения.Добавить(Ссылка2);

ЗаписьXML = Новый ЗаписьXML;
ЗаписьXML.УстановитьСтроку();
СериализаторXDTO.ЗаписатьXML(ЗаписьXML, СписокДляСохранения);
СтрокаНастройки = ЗаписьXML.Закрыть(); // Эту строку пишем в значение настройки

// Десериализация (чтение из строки)
ЧтениеXML = Новый ЧтениеXML;
ЧтениеXML.УстановитьСтроку(СтрокаНастройки);
СписокЗагруженный = СериализаторXDTO.ПрочитатьXML(ЧтениеXML);

Важный момент: При таком подходе система не отслеживает ссылки. Если элемент справочника будет удален физически, при десериализации вы получите объект <Объект не найден...>. Это нужно учитывать при написании алгоритмов обработки этих настроек.

Решение 4: Использование Хранилища Настроек (для платформы 8.3)

Если ваша конфигурация работает на платформе 8.3, мы можем воспользоваться механизмом ХранилищеОбщихНастроек. Это системная таблица, которая позволяет хранить любые сериализуемые данные (включая массивы, структуры и списки значений) без привязки к ПВХ.

Посмотрим на пример работы с этим механизмом:


// Сохранение списка значений под ключом
КлючОбъекта = "ОтборыДляСпецификаций";
КлючНастройки = "СписокИсключенийНоменклатуры";
ХранилищеОбщихНастроек.Сохранить(КлючОбъекта, КлючНастройки, ВашСписокЗначений, , ПользователиИнформационнойБазы.ТекущийПользователь().Имя);

// Загрузка
ВашСписокЗначений = ХранилищеОбщихНастроек.Загрузить(КлючОбъекта, КлючНастройки, , ПользователиИнформационнойБазы.ТекущийПользователь().Имя);
Если ВашСписокЗначений = Неопределено Тогда
    ВашСписокЗначений = Новый СписокЗначений;
КонецЕсли;

Резюме и рекомендации

Подведем итог нашему анализу:

  1. Если вам нужно использовать выбранные элементы в запросах (например, для фильтрации в отчетах), выбирайте Решение 1 (Регистр сведений). Это обеспечит максимальную скорость работы и чистоту кода.
  2. Если стоит задача минимального изменения конфигурации и данные нужны только «внутри» одной обработки, используйте Решение 3 (Сериализация в XML), сохраняя строку в стандартную настройку.
  3. Если вы работаете в современной среде и настройки не связаны со старым ПВХ «Настройки пользователей», используйте Хранилище настроек (Решение 4).

Помните, что при реализации множественного выбора важно всегда проверять права пользователя на чтение выбранных элементов, так как в списках могут оказаться объекты, к которым у пользователя пропал доступ со временем.

← На главную