Часто при работе с управляемыми формами в 1С возникает задача: нужно предоставить пользователю выбор из списка, где каждый элемент имеет внутренний идентификатор (например, GUID) и понятное человеку представление (например, "Пользователь Иванов"). Стандартное поведение платформы таково, что после выбора в поле отображается именно внутреннее значение, что неудобно и неинформативно для пользователя. Давайте разберем, почему так происходит и как это исправить.
Проанализируем ситуацию. У нас есть реквизит формы с типом СписокЗначений. Мы заполняем его элементами, у каждого из которых есть Значение (например, уникальный идентификатор из внешней системы) и Представление (текстовое описание). На форме этот реквизит выведен как поле ввода с кнопкой выбора из списка. При нажатии на кнопку пользователь видит красивый список с представлениями, но как только он делает выбор, поле заполняется некрасивым идентификатором.
Причина такого поведения кроется в механизме связывания данных. Поле на форме напрямую связано с реквизитом, и платформа записывает в него именно Значение выбранного элемента, так как оно соответствует типу данных. Представление используется лишь как подсказка в момент выбора. Наша задача — "обмануть" механизм отображения, не меняя при этом хранимое значение. Рассмотрим несколько способов решения этой задачи.
Это самый гибкий и часто используемый метод для решения подобных задач. Идея заключается в том, чтобы подменить отображаемый в поле текст, не затрагивая его реальное значение. Условное оформление позволяет задавать правила, по которым внешний вид элементов формы будет меняться в зависимости от данных.
Разберем по шагам, как это работает. Нам нужно для каждого возможного значения из списка создать правило: "Если значение в поле равно X, то отображать текст Y".
Этот подход особенно хорош, когда список значений динамический и загружается, например, из внешнего веб-сервиса. В этом случае настраивать оформление вручную неудобно, поэтому мы будем делать это программно.
Посмотрим на пример программной настройки:
Предположим, у нас есть процедура на сервере, которая получает данные для выбора и заполняет список. В этой же процедуре мы динамически создадим элементы условного оформления.
Пользователи с типом СписокЗначений.ПриСозданииНаСервере получаем данные и заполняем список выбора для нашего поля, а также программно настраиваем условное оформление.
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
// 1. Очищаем старые настройки, если они есть
Элементы.Пользователи.СписокВыбора.Очистить();
УсловноеОформление.Элементы.Очистить();
// 2. Получаем данные для выбора.
// В реальной задаче здесь будет запрос к веб-сервису или к базе данных.
// Для примера создадим структуру.
ВариантыВыбора = Новый Структура;
ВариантыВыбора.Вставить("a1b2c3d4-e5f6-g7h8-i9j0-k1l2m3n4o5p6", "Иванов Иван Иванович");
ВариантыВыбора.Вставить("b2c3d4e5-f6g7-h8i9-j0k1-l2m3n4o5p6q7", "Петров Петр Петрович");
ВариантыВыбора.Вставить("c3d4e5f6-g7h8-i9j0-k1l2-m3n4o5p6q7r8", "Сидоров Сидор Сидорович");
// 3. Заполняем список выбора для элемента формы и программно создаем условное оформление
Для Каждого КлючИЗначение Из ВариантыВыбора Цикл
// Добавляем элемент в выпадающий список
Элементы.Пользователи.СписокВыбора.Добавить(КлючИЗначение.Ключ, КлючИЗначение.Значение);
// Создаем новый элемент условного оформления
ЭлементУсловногоОформления = УсловноеОформление.Элементы.Добавить();
// Указываем, что оформлять будем поле "Пользователи"
ОформляемоеПоле = ЭлементУсловногоОформления.Поля.Элементы.Добавить();
ОформляемоеПоле.Поле = Новый ПолеКомпоновкиДанных("Пользователи");
// Настраиваем отбор: правило будет срабатывать для конкретного значения
ЭлементОтбора = ЭлементУсловногоОформления.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
ЭлементОтбора.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Объект.Пользователи"); // Путь к данным реквизита
ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
ЭлементОтбора.ПравоеЗначение = КлючИЗначение.Ключ; // GUID нашего пользователя
// Настраиваем оформление: устанавливаем нужный текст
ЭлементУсловногоОформления.Оформление.УстановитьЗначениеПараметра("Текст", КлючИЗначение.Значение);
КонецЦикла;
КонецПроцедуры
Что мы сделали? Мы в цикле обошли все возможные варианты. Для каждого варианта мы добавили элемент в список выбора (чтобы пользователь мог его выбрать) и создали персональное правило в условном оформлении. Это правило "говорит" форме: "когда в реквизите Объект.Пользователи будет лежать значение-идентификатор, покажи вместо него текст-представление".
Преимущества:
Недостатки:
Платформа 1С предоставляет более системный и "правильный" механизм для подобных задач, особенно если речь идет о множественном выборе. Вместо реквизита типа СписокЗначений можно использовать ТаблицаЗначений.
Разберем по шагам:
ВыбранныеПользователи) с типом ТаблицаЗначений.Идентификатор (тип УникальныйИдентификатор или Строка) и Представление (тип Строка).ПутьКДаннымЗначения и указываем в нем имя нашей колонки с идентификаторами — Идентификатор.ПутьКДаннымПредставления и указываем имя колонки с представлениями — Представление.Элементы.ВыбранныеПользователи.СписокВыбора) так же, как мы делали в первом способе.После этих настроек платформа сама будет понимать, откуда брать значение для сохранения, а откуда — текст для отображения. При выборе элемента в реквизит-таблицу будет добавлена новая строка, где будут заполнены обе колонки: и Идентификатор, и Представление.
Преимущества:
В обсуждении на форуме был предложен еще один вариант — обрабатывать событие изменения поля на клиенте. Этот метод имеет свою специфику и подходит не во всех случаях.
Идея в том, чтобы после выбора значения пользователем принудительно обновить представление у элементов реквизита СписокЗначений.
&НаКлиенте
Процедура ПользователиПриИзменении(Элемент)
// Перебираем элементы в реквизите формы "Пользователи"
Для Индекс = 0 По Пользователи.Количество() - 1 Цикл
ЭлементСписка = Пользователи[Индекс];
// Если представление не заполнено, находим его в списке выбора
Если НЕ ЗначениеЗаполнено(ЭлементСписка.Представление) Тогда
НайденныйЭлементВыбора = Элементы.Пользователи.СписокВыбора.НайтиПоЗначению(ЭлементСписка.Значение);
Если НайденныйЭлементВыбора <> Неопределено Тогда
ЭлементСписка.Представление = НайденныйЭлементВыбора.Представление;
КонецЕсли;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Важный нюанс: Этот подход сработает корректно, если ваш реквизит СписокЗначений отображается на форме в виде таблицы, где видны и значение, и представление. Если же он выведен как простое поле ввода, то этот код, скорее всего, не изменит отображение в самом поле, так как поле показывает строковое представление всего объекта СписокЗначений, а не его отдельных элементов.
Проанализировав ситуацию, мы можем дать следующие рекомендации:
ТаблицаЗначений с настройкой свойств ПутьКДаннымЗначения и ПутьКДаннымПредставления.Таким образом, стандартное поведение платформы можно и нужно настраивать под свои задачи, используя мощные инструменты, которые она предоставляет.