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