Часто разработчики сталкиваются с парадоксальной ситуацией: при программном заполнении табличной части документа на управляемой форме отладчик показывает, что данные в объекте (например, Объект.Товары) успешно созданы и заполнены, однако после завершения выполнения кода на самой форме эти строки остаются пустыми. Рассмотрим подробнее основные причины такого поведения платформы и разберем по шагам рабочие способы решения этой проблемы.
Проанализируем первую и самую неочевидную причину, из-за которой форма может "терять" заполненные нами данные. Если заполнение вызывается по нажатию кнопки на управляемой форме, необходимо обратить внимание на свойства самой команды.
У команд формы есть флажок Изменяет сохраняемые данные. Если этот флаг установлен в значение Истина, платформа 1С после выполнения серверного вызова (кода команды) автоматически перепроверяет состояние объекта. В некоторых ситуациях это приводит к тому, что форма заново "перечитывает" данные из базы данных, затирая все изменения в оперативной памяти, которые мы только что сделали программно, но еще не успели записать.
Решение: Посмотрим на свойства вашей команды и снимем галочку Изменяет сохраняемые данные. Зачастую одного этого действия достаточно, чтобы форма перестала сбрасывать заполненные строки табличной части.
Разберем ситуацию на примере документа "Установка цен номенклатуры" (УТ 11, ERP, КА). Это один из самых сложных документов с точки зрения интерфейса.
Проблема заключается в том, что мы можем заполнять реальную табличную часть документа Товары, но на форме физически отображается совершенно другой элемент! В типовых конфигурациях для этого документа часто используется вспомогательный реквизит формы — например, ДеревоЦен (тип ДанныеФормыДерево). При открытии формы данные перекладываются из табличной части в это дерево.
Если мы программно заполняем Объект.Товары, но не вызываем служебные процедуры обновления дерева, интерфейс формы останется пустым.
Решение: Выясним, с каким именно реквизитом связан элемент управления на форме. Если это динамическое дерево или список, после стандартного использования ЗначениеВРеквизитФормы необходимо вызвать типовую клиентскую или серверную процедуру пересчета формы (например, РассчитатьЦены, ОбновитьЭлементыФормы или процедуру инициализации колонок). Для проверки структуры элементов и их связи с данными прямо в пользовательском интерфейсе подойдёт инструмент для исследования свойств форм в режиме предприятия.
Рассмотрим еще один интересный случай, с которым сталкиваются при программном заполнении документов вроде "План закупок" или "Сборка товаров".
Посмотрим на классический пример кода, который часто пишут для заполнения формы "снаружи":
&НаСервере
Функция СоздатьПланЗакупокНаСервере(ДокОб)
Док = ДанныеФормыВЗначение(ДокОб, Тип("ДокументОбъект.ПланЗакупок"));
Док.Дата = ТекущаяДата;
// Заполняем ТЧ
Товары = Док.Товары;
НовТов = Товары.Добавить();
НовТов.Количество = 1;
ЗначениеВДанныеФормы(Док, ДокОб);
КонецФункции
&НаКлиенте
Процедура СоздатьПланЗакупок(Команда)
ФормаДок = ПолучитьФорму("Документ.ПланЗакупок.ФормаОбъекта");
Об = ФормаДок.Объект;
СоздатьПланЗакупокНаСервере(Об);
КопироватьДанныеФормы(Об, ФормаДок.Объект);
ФормаДок.Открыть();
КонецПроцедуры
При отладке этого кода мы видим, что строка добавлена, но при открытии формы — пусто. Выясним причину: такие документы поддерживают так называемые "виды отображения" (например, отображение простым списком или иерархией).
Данные находятся в Объект.Товары, но сама управляемая форма в текущий момент может отображать скрытую таблицу или группу Элементы.ТаблицаТоварыИерархия, которая не синхронизируется автоматически при грубом копировании данных формы. В этом случае необходимо переключать программно режим просмотра или заполнять данные строго до вызова отрисовки.
В приведенном выше примере есть еще одна архитектурная ошибка. Разберем, почему использование ПолучитьФорму для инициализации новых данных часто приводит к проблемам.
ПолучитьФорму, платформа немедленно отрабатывает событие формы ПриСозданииНаСервере.Объект у уже созданной в памяти формы, мы вступаем в конфликт с внутренними обработчиками 1С. Форма может проигнорировать внешние "вливания" через КопироватьДанныеФормы.Решение: Вместо того чтобы "вталкивать" данные в готовую форму, воспользуемся передачей параметров заполнения. Создадим структуру параметров и передадим её в метод ОткрытьФорму. Это заставит саму форму (через ОбработкуЗаполнения или события при создании) корректно инициировать все таблицы, деревья цен и виды отображения.
Давайте резюмируем чек-лист для исправления ситуации с пустыми табличными частями:
Изменяет сохраняемые данные у команды на форме.Объект.Товары или вспомогательному дереву/таблице значений).ЗначениеВРеквизитФормы ищем и вызываем типовую экспортную процедуру формы, отвечающую за обновление интерфейса.ПолучитьФорму. Лучше передавать параметры заполнения в ОткрытьФорму или заполнять сам ДокументОбъект до вызова интерфейса, чтобы отработала стандартная логика 1С.ЭтаФорма.ОбновитьОтображениеДанных(), чтобы заставить систему принудительно синхронизировать кэш формы и визуальные элементы управления.