Как программно заполнить табличную часть документа и корректно отобразить изменения в форме

Программист 1С v8.3 (Управляемые формы)
← На главную

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

Почему изменения в объекте не видны в форме?

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

Проанализируем ситуацию: ваш измененный объект существует в оперативной памяти сервера лишь мгновение, пока выполняется код обработки. Если вы не вызвали метод Записать(), эти изменения не попадут в базу данных. А форма при открытии «знает» только о ссылке и берет данные именно из базы. Таким образом, мы получаем две независимые копии документа: одну измененную в памяти и одну старую в интерфейсе.

Решение для обычных форм (Толстый клиент)

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


// 1. Получаем объект из ссылки
ДокОбъект = СсылкаНаДокумент.ПолучитьОбъект();

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

// 3. Получаем форму ИМЕННО ОТ ОБЪЕКТА, а не от ссылки
ФормаДокумента = ДокОбъект.ПолучитьФорму("ФормаОбъекта");

// 4. Теперь форма содержит измененные данные
ФормаДокумента.Открыть();

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

Решение для управляемых форм (Управляемое приложение)

В управляемом приложении 1С 8.3 всё сложнее из-за четкого разделения на клиент и сервер. Метод ПолучитьОбъект() работает на сервере, а открытие формы инициируется с клиента. Чтобы передать изменения, не записывая их в базу данных, рекомендуется использовать механизм параметров формы.

Способ 1: Использование параметра «ЗначениеЗаполнения»

Это наиболее «чистый» и правильный с точки зрения архитектуры 1С метод. Мы передаем данные в структуру параметров, которую форма документа обрабатывает при создании. Рассмотрим этот метод по шагам.

Шаг 1. Код в обработке (на клиенте):


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

// Формируем параметры открытия
ПараметрыФормы = Новый Структура;
ПараметрыФормы.Вставить("ДанныеДляЗаполненияТЧ", ДанныеДляТЧ);

// Открываем форму существующего документа
ПараметрыВыбора = Новый Структура("Ключ", СсылкаНаДокумент);
ОткрытьФорму("Документ.БюджетПродаж.ФормаОбъекта", ПараметрыВыбора, , , , , Новый ОписаниеОповещения("ПослеЗакрытияФормы", ЭтотОбъект), РежимОткрытияОкнаФормы.БлокироватьВесьИнтерфейс);

Шаг 2. Код в модуле формы документа:

В форме документа необходимо перехватить переданные данные в обработчике ПриСозданииНаСервере или ОбработкаЗаполнения.


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

Способ 2: Использование временного хранилища

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

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


// В обработке на сервере
АдресХранилища = ПоместитьВоВременноеХранилище(ИзмененныйОбъект, УникальныйИдентификатор);
ПараметрыФормы = Новый Структура("АдресОбъекта", АдресХранилища);
ОткрытьФорму("Документ.ИмяДокумента.ФормаОбъекта", ПараметрыФормы);

// В форме документа ПриСозданииНаСервере
Если Параметры.Свойство("АдресОбъекта") Тогда
    ИзмененныйОбъект = ПолучитьИзВременногоХранилища(Параметры.АдресОбъекта);
    КопироватьДанныеФормы(ИзмененныйОбъект, Объект);
КонецЕсли;

Использование метода КопироватьДанныеФормы крайне важно. Он позволяет корректно перенести данные из программного объекта (типа ДокументОбъект) в реквизит формы (типа ДанныеФормыСтруктура).

Особенности работы с проведенными документами

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

  1. Режим «Только просмотр»: Если форма открывается для проведенного документа, а у пользователя нет прав на редактирование проведенных документов или закрыт период, форма может открыться в режиме «Только чтение». В этом случае программное заполнение в коде сработает, но пользователь увидит серые, недоступные для правки поля.
  2. Перепроведение: Помните, что простое заполнение ТЧ в форме не меняет движения в регистрах. Чтобы изменения вступили в силу в учете, пользователю необходимо будет нажать кнопку «Провести» в открытой форме.
  3. Сброс данных при открытии: Проверьте обработчики ПриОткрытии и ПриЧтенииНаСервере в модуле формы документа. Часто там прописана логика пересчета цен или заполнения по умолчанию, которая может затереть ваши программно переданные данные.

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

← На главную