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