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