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