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