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