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