Почему не выводится текст из ячейки табличной части 1С и как это исправить

Программист 1С v8.3 (Обычные формы) IT и автоматизация бизнеса
← На главную

При работе с табличными полями в обычных формах 1С разработчики часто сталкиваются с ситуацией: визуально в ячейке таблицы отображается нужный текст или код, но при попытке программно прочитать его через ЭлементыФормы.ТаблицаТоваров.ТекущаяСтрока.ИнвНомер считывается пустое значение. При этом, если ввести значение в ячейку вручную, код начинает работать корректно.

В этой статье мы разберем причину такого поведения платформы 1С, выясним разницу между данными строки и оформлением ячейки, а также рассмотрим несколько проверенных способов решения этой проблемы.

Разбор причины: разделение слоя данных и слоя оформления

Для понимания логики работы платформы проанализируем, как формируется отображение данных в табличном поле обычных форм. Когда в событии ПриВыводеСтроки задается текст ячейки:


Процедура ТаблицаТоваровПриВыводеСтроки(Элемент, ОформлениеСтроки, ДанныеСтроки)
    Если ЗначениеЗаполнено(ДанныеСтроки.Товар) Тогда
        ОформлениеСтроки.Ячейки["ИнвНомер"].Текст = ДанныеСтроки.Товар.СлужебныйИнвНомер;
        ОформлениеСтроки.Ячейки["ИнвНомер"].ОтображатьТекст = Истина;
    КонецЕсли;
КонецПроцедуры

В данном случае свойство ОформлениеСтроки.Ячейки["..."].Текст меняет исключительно визуальное представление в графическом интерфейсе пользователя. Объект ОформлениеСтроки не связан с хранилищем данных табличной части или таблицы значений.

Платформа 1С строго разделяет слой данных (объект ДанныеСтроки) и слой оформления (объект ОформлениеСтроки):

  1. Данные строки (слой данных) — реквизиты табличной части или колонки таблицы значений. Именно из них считывается значение при обращении к ТекущаяСтрока.ИнвНомер.
  2. Оформление строки (слой отображения) — динамические свойства визуальных ячеек (цвет, шрифт, текст представления). Текст оформления используется только для отрисовки на экране и существует исключительно в момент вызова событий перерисовки интерфейса.

По этой причине при вызове метода Сообщить(ЭлементыФормы.ТаблицаТоваров.ТекущаяСтрока.ИнвНомер) программа обращается к источнику данных, где реквизит ИнвНомер остается пустым, несмотря на заполненный текст на экране.

Способ 1. Использование невидимой колонки в источнике данных

Если необходимо сохранить вычисленное значение в источнике данных, чтобы обращаться к нему из других процедур формы, заведем дополнительную колонку в источнике данных (например, в табличной части или таблице значений).

Рассмотрим порядок действий по шагам:

  1. Добавим в источник данных табличной части новую колонку (например, ИнвНомСкр) с типом Строка.
  2. Если эту колонку не требуется показывать пользователю, сделаем ее невидимой на форме.
  3. Запишем значение в данные строки при ее выводе:

Процедура ТаблицаТоваровПриВыводеСтроки(Элемент, ОформлениеСтроки, ДанныеСтроки)
    Если ЗначениеЗаполнено(ДанныеСтроки.Товар) Тогда
        ОформлениеСтроки.Ячейки["ИнвНомер"].Текст = ДанныеСтроки.Товар.СлужебныйИнвНомер;
        ОформлениеСтроки.Ячейки["ИнвНомер"].ОтображатьТекст = Истина;
        
        // Записываем значение напрямую в данные строки
        ДанныеСтроки.ИнвНомСкр = ДанныеСтроки.Товар.СлужебныйИнвНомер;
    КонецЕсли;
КонецПроцедуры

Теперь при переключении страниц или нажатии кнопок можно безопасно считывать данные из текущей строки:


Процедура Панель1ПриСменеСтраницы(Элемент, ТекущаяСтраница)
    Если ТекущаяСтраница = 2 Тогда
        Если ЭлементыФормы.ТаблицаТоваров.ТекущаяСтрока <> Неопределено Тогда
            Сообщить(ЭлементыФормы.ТаблицаТоваров.ТекущаяСтрока.Товар);
            Сообщить(ЭлементыФормы.ТаблицаТоваров.ТекущаяСтрока.ИнвНомСкр);
        КонецЕсли;
    КонецЕсли;
КонецПроцедуры

Способ 2. Прямое обращение к реквизитам через ссылку

В ситуациях, когда выводимый текст берется из реквизита ссылочного объекта (например, справочника Товары), нет необходимости заводить дополнительные невидимые колонки.

Проанализируем ситуацию: если значение СлужебныйИнвНомер хранится в справочнике, мы можем считать его напрямую через точку от реквизита Товар в любой момент времени:


Процедура Панель1ПриСменеСтраницы(Элемент, ТекущаяСтраница)
    Если ТекущаяСтраница = 2 Тогда
        ТекущаяСтрока = ЭлементыФормы.ТаблицаТоваров.ТекущаяСтрока;
        Если ТекущаяСтрока <> Неопределено И ЗначениеЗаполнено(ТекущаяСтрока.Товар) Тогда
            Сообщить(ТекущаяСтрока.Товар);
            Сообщить(ТекущаяСтрока.Товар.СлужебныйИнвНомер);
        КонецЕсли;
    КонецЕсли;
КонецПроцедуры

Важно: Обращение к ТекущаяСтрока всегда стоит оборачивать проверкой на Неопределено. Если табличная часть пуста или ни одна строка не выделена, прямое обращение вызовет критическую ошибку «Значение не является значением объектного типа».

Способ 3. Оптимизация работы через событие ПриПолученииДанных

Обращение к реквизитам через точку (ДанныеСтроки.Товар.СлужебныйИнвНомер) внутри события ПриВыводеСтроки может существенно замедлять работу интерфейса при прокрутке таблицы. Это происходит потому, что платформа делает отдельный неявный запрос к базе данных для каждой видимой строки.

Чтобы избежать задержек, оптимизируем вывод с помощью события ПриПолученииДанных. Оно обрабатывает сразу весь массив видимых строк в один прием:


Процедура ТаблицаТоваровПриПолученииДанных(Элемент, ОформленияСтрок)
    МассивТоваров = Новый Массив;
    Для Каждого ОформлениеИз Списка ОформленияСтрок Цикл
        Если ЗначениеЗаполнено(ОформлениеИз.ДанныеСтроки.Товар) Тогда
            МассивТоваров.Добавить(ОформлениеИз.ДанныеСтроки.Товар);
        КонецЕсли;
    КонецЦикла;

    Если МассивТоваров.Количество() = 0 Тогда
        Возврат;
    КонецЕсли;

    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |	Товары.Ссылка КАК Товар,
        |	Товары.СлужебныйИнвНомер КАК ИнвНомер
        |ИЗ
        |	Справочник.Товары КАК Товары
        |ГДЕ
        |	Товары.Ссылка В(&МассивТоваров)";
    Запрос.УстановитьПараметр("МассивТоваров", МассивТоваров);
    ТаблицаИнвНомеров = Запрос.Выполнить().Выгрузить();

    Для Каждого ОформлениеИз Списка ОформленияСтрок Цикл
        ТоварСсылка = ОформлениеИз.ДанныеСтроки.Товар;
        НайденнаяСтрока = ТаблицаИнвНомеров.Найти(ТоварСсылка, "Товар");
        Если НайденнаяСтрока <> Неопределено Тогда
            ОформлениеИз.Ячейки.ИнвНомер.УстановитьТекст(НайденнаяСтрока.ИнвНомер);
        КонецЕсли;
    КонецЦикла;
КонецПроцедуры

Использование события ПриПолученииДанных обеспечивает высокий уровень производительности формы и гарантирует плавную прокрутку большого количества строк.

← На главную