В практике разработки на платформе 1С:Предприятие 8.3 часто возникает задача кастомизации интерфейса под конкретные требования бизнес-логики. Типичный пример: в справочнике Подразделения достаточно видеть только краткое наименование, но в документе Заявка пользователю жизненно важно видеть иерархию (например, «Цех №1, Головной офис»), чтобы не ошибиться при вводе данных. В этой статье мы подробно разберем, почему стандартный механизм ОбработкаПолученияПредставления не всегда подходит для этой задачи, и изучим альтернативные методы реализации.
Рассмотрим код, который часто пытаются использовать начинающие разработчики в модуле менеджера справочника:
Процедура ОбработкаПолученияПредставления(Данные, Представление, СтандартнаяОбработка)
НаименованиеГорода = "";
Если Данные.Ссылка <> Неопределено Тогда
СтандартнаяОбработка = Ложь;
текПодразделение = Данные.Ссылка.Родитель;
Пока ЗначениеЗаполнено(текПодразделение.Родитель) Цикл
текПодразделение = текПодразделение.Родитель;
КонецЦикла;
Представление = СокрЛП(Данные.Ссылка.Наименование) + ", " + СокрЛП(текПодразделение);
КонецЕсли;
КонецПроцедуры
Этот код отлично справляется с изменением текста во всей системе. Однако у него есть два критических недостатка:
Подразделения срабатывает везде — в списках, в других документах, в отчетах. У этого метода нет встроенного параметра, который бы подсказал, из какой формы или документа вызвано получение представления.Пока для поиска родителя внутри этого обработчика — это классическая проблема N+1 запросов. Если вы откроете динамический список с 50 строками, система выполнит десятки дополнительных обращений к базе данных, что приведет к ощутимым «тормозам» интерфейса.Выясним, какими способами можно добиться нужного результата локально, только для формы документа Заявка.
Это самый «чистый» способ, не требующий изменения структуры данных или глобальных модулей. Механизм Условного оформления в управляемых формах позволяет подменять отображаемый текст в полях ввода и колонках таблиц.
Разберем реализацию по шагам:
Заявка.Подразделение.Чтобы текст менялся динамически на основе данных, мы можем управлять этим оформлением программно в событии ПриЧтенииНаСервере или ПриИзменении реквизита. Проанализируем пример кода для программной установки текста в элементе формы:
&НаСервере
Процедура ОбновитьПредставлениеПодразделения()
// Вычисляем нужное нам представление
Если ЗначениеЗаполнено(Объект.Подразделение) Тогда
РодительНазвание = Объект.Подразделение.Родитель.Наименование;
НовоеПредставление = Строка(Объект.Подразделение) + ", " + РодительНазвание;
// Устанавливаем текст через элемент оформления
Для Каждого ЭлементОформления Из УсловноеОформление.Элементы Цикл
Если ЭлементОформления.ОформляемыеПоля.Элементы[0].Поле = Новый ПолеКомпоновкиДанных("Подразделение") Тогда
ЭлементОформления.ПараметрыОформления.УстановитьЗначениеПараметра("Текст", НовоеПредставление);
КонецЕсли;
КонецЦикла;
КонецЕсли;
КонецПроцедуры
Если нам нужно изменить представление только в одном поле ввода, мы можем использовать «трюк» с подменой реквизита. Это решение часто оказывается самым надежным для пользователя.
Рассмотрим алгоритм действий:
Заявка новый реквизит ПодразделениеПредставление с типом Строка.Подразделение.НачалоВыбора программно открываем форму выбора справочника Подразделения.Объект.Подразделение, а в строковый реквизит выводим наше расширенное наименование (Наименование + Родитель).Посмотрим на пример обработки выбора:
&НаКлиенте
Процедура ПодразделениеПредставлениеОбработкаВыбора(Элемент, ВыбранноеЗначение, СтандартнаяОбработка)
СтандартнаяОбработка = Ложь;
Объект.Подразделение = ВыбранноеЗначение;
// Вызываем серверную функцию для формирования красивой строки
ПодразделениеПредставление = СформироватьПолноеНазвание(ВыбранноеЗначение);
КонецПроцедуры
Чтобы пользователь видел правильное представление не только после выбора, но и в процессе набора текста с клавиатуры, необходимо использовать событие АвтоПодбор.
Проанализируем ситуацию: когда пользователь вводит первые буквы названия, система обращается к серверу за списком подходящих элементов. Мы можем перехватить этот список и заменить в нем стандартные наименования на те, что включают родителя.
&НаКлиенте
Процедура ПодразделениеАвтоПодбор(Элемент, Текст, ДанныеВыбора, Параметры, Ожидание, СтандартнаяОбработка)
СтандартнаяОбработка = Ложь;
// Здесь мы вызываем серверный поиск, который возвращает массив структур
// со значениями (ссылка) и представлениями (строка "Подразделение + Родитель")
ДанныеВыбора = ПоискПодразделенийСРодителемНаСервере(Текст);
КонецПроцедуры
Как справедливо отмечено в обсуждении темы, любые манипуляции с получением родителей в цикле могут замедлить работу. Если вы решите использовать расширенное представление в динамическом списке документов Заявка, лучше всего сделать это через Произвольный запрос в настройках динамического списка.
Рассмотрим пример запроса для списка:
ВЫБРАТЬ
Док.Ссылка КАК Ссылка,
Док.Номер КАК Номер,
Док.Дата КАК Дата,
Док.Подразделение.Наименование + ", " + ЕСТЬNULL(Док.Подразделение.Родитель.Наименование, "") КАК ПодразделениеПредставление
ИЗ
Документ.Заявка КАК Док
Использование конструкции ЕСТЬNULL и прямое обращение через точку в запросе позволяют платформе эффективно сформировать SQL-запрос с LEFT JOIN, что работает в десятки раз быстрее, чем перебор в коде 1С.
Мы проанализировали несколько способов решения задачи. Подведем итоги:
АвтоПодбор.Помните: изменение ОбработкаПолученияПредставления в модуле менеджера — это крайняя мера, которую стоит применять только тогда, когда представление должно измениться абсолютно во всей конфигурации без исключений.