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