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

Программист IT и автоматизация бизнеса
← На главную

При разработке интерфейсов на Обычных формах в системе 1С:Предприятие 8 программисты часто сталкиваются с неприятным эффектом: после программного добавления колонки в ТабличноеПоле и выбора в ней значения, введенные данные бесследно исчезают, как только пользователь переключает фокус на другую ячейку или закрывает режим редактирования. Однако при повторном нажатии на ячейку значение может магическим образом «всплывать» обратно.

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

Выясним причину: почему данные «исчезают»?

Для начала проанализируем ситуацию с точки зрения архитектуры платформы. В «Обычных формах» элемент управления ТабличноеПоле является лишь визуальным отражением какого-либо источника данных (например, ТаблицаЗначений, СписокЗначений или РегистрСведенийСписок).

Когда мы создаем колонку программно или в конфигураторе, но оставляем свойство Данные (Data) пустым, мы создаем «виртуальную» колонку. Вот что происходит на уровне системы:

  1. Пользователь входит в режим редактирования ячейки.
  2. Платформа динамически создает элемент управления (например, ПолеВвода) и помещает его в границы ячейки.
  3. Пользователь выбирает значение. Это значение временно хранится в самом элементе управления.
  4. Пользователь завершает редактирование (нажимает Enter или уходит из ячейки).
  5. Критический момент: Платформа пытается записать введенное значение в источник данных, указанный в свойстве Данные. Если это свойство пустое, записывать значение некуда. Визуальный элемент управления уничтожается, а значение теряется, так как оно не было привязано к объекту хранения.

Повторное появление значения при входе в режим редактирования — это следствие кэширования отрисовки, но для системы этого значения не существует, и в отчеты или алгоритмы оно не попадет.

Способ 1. Привязка к источнику данных (Рекомендуемый)

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

Предположим, у нас есть ТабличноеПоле1, источником данных которого является ТаблицаЗначений. Нам нужно добавить колонку «ВыборПользователя».


// 1. Сначала добавляем колонку в саму Таблицу Значений (объект-источник)
НовыйТип = Новый ОписаниеТипов("СправочникСсылка.Номенклатура");
ТаблицаДанных = ЭлементыФормы.ТабличноеПоле1.Значение;
ТаблицаДанных.Колонки.Добавить("ВыборПользователя", НовыйТип);

// 2. Теперь добавляем визуальную колонку в Табличное Поле
НоваяКолонка = ЭлементыФормы.ТабличноеПоле1.Колонки.Добавить("ВыборПользователя", "Выбор номенклатуры");

// 3. Устанавливаем связь! Это самый важный шаг
НоваяКолонка.Данные = "ВыборПользователя";

// 4. Настраиваем элемент управления для выбора
НоваяКолонка.РежимРедактирования = РежимРедактированияКолонки.ВходПриВводе;

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

Способ 2. Использование события ПриВыводеСтроки

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

Рассмотрим алгоритм реализации этого метода:

  1. Создаем внешнее хранилище для данных (например, объект Соответствие), где ключом будет идентификатор строки, а значением — выбор пользователя.
  2. При изменении значения в ячейке записываем его в это хранилище.
  3. В событии ПриВыводеСтроки принудительно подставляем текст или значение в ячейку.

Посмотрим на пример реализации:


// В модуле формы создаем переменную для хранения данных
Перем мХранилищеДанных;

Процедура ПриОткрытии()
    мХранилищеДанных = Новый Соответствие;
КонецПроцедуры

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

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

Важный нюанс: использование ОформлениеСтроки.Ячейки.ИмяКолонки.УстановитьТекст() позволяет визуализировать данные даже тогда, когда они физически не хранятся в основной таблице. Однако помните, что событие ПриВыводеСтроки вызывается очень часто (при каждой прокрутке), поэтому код внутри него должен быть максимально оптимизирован.

Способ 3. Установка типов значений для колонки

Проанализируем ситуацию, упомянутую в обсуждении: иногда тип значения назначается только элементу управления (полю ввода), а не самой колонке. В Обычных формах это критично.

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

При программном создании колонки всегда четко определяйте ОписаниеТипов:


// Правильное создание типа данных колонки
МассивТипов = Новый Массив;
МассивТипов.Добавить(Тип("Число"));
ОписаниеТиповЧ = Новый ОписаниеТипов(МассивТипов);

НоваяКолонка = ЭлементыФормы.ТабличноеПоле1.Колонки.Добавить("Сумма");
НоваяКолонка.ТипЗначения = ОписаниеТиповЧ;

Без установки ТипЗначения для всей колонки, даже при наличии привязки к данным, вы можете столкнуться с некорректным отображением информации.

Рекомендации по производительности

Если в вашем табличном поле планируется вывод тысяч строк с программно вычисляемыми данными, использование ПриВыводеСтроки может замедлить интерфейс («фризы» при прокрутке). В таких случаях проанализируем возможность использования события ПриПолученииДанных.

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

Подведем итог: Для того чтобы значения в программной колонке не пропадали, всегда стремитесь использовать связь через свойство Данные с предварительным расширением колонок источника (Таблицы значений). Если это невозможно — используйте событийную модель отрисовки и внешние структуры для хранения введенных пользователем данных.

← На главную