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

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

При разработке внешних обработок в среде 1С:Предприятие 8.3 программисты часто сталкиваются с необходимостью автоматизировать создание документов. Типовые конфигурации (например, ЗУП 3.1, ERP или КА) содержат сложную логику заполнения, вынесенную в общие модули. Попытка вызвать штатные процедуры вроде ВедомостьПриСозданииНаСервере напрямую из внешнего кода часто приводит к ошибкам типа «Поле объекта не обнаружено (Параметры)» или «Ошибка преобразования данных XDTO». Рассмотрим подробно, почему это происходит и как правильно решить данную задачу.

Разбор причины ошибки: почему нельзя передать форму

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

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

Решение №1: Программное создание и заполнение объекта без формы

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

Рассмотрим пример кода, который создает документ ВедомостьНаВыплатуЗарплатыВБанк и заполняет его через стандартные механизмы объекта:


&НаСервере
Процедура СоздатьВедомостьПрограммно()
    
    // Создаем новый объект документа
    НовыйДок = Документы.ВедомостьНаВыплатуЗарплатыВБанк.СоздатьДокумент();
    
    // Устанавливаем базовые реквизиты
    НовыйДок.Дата = ТекущаяДата();
    НовыйДок.ПериодРегистрации = НачалоМесяца(ТекущаяДата());
    НовыйДок.Организация = Справочники.Организации.НайтиПоНаименованию("Наша организация");
    
    // Вызываем заполнение, которое обычно срабатывает при создании
    // В типовых конфигурациях логика заполнения часто находится в ОбработкаЗаполнения
    НовыйДок.Заполнить(Неопределено); 
    
    // Если нужно заполнить табличную часть по данным учета, ищем методы в модуле менеджера
    // Например, для ЗУП это может быть вызов специализированного серверного модуля
    ПараметрыЗаполнения = Новый Структура;
    ПараметрыЗаполнения.Вставить("Месяц", НовыйДок.ПериодРегистрации);
    // Документы.ВедомостьНаВыплатуЗарплатыВБанк.ЗаполнитьПоДаннымУчета(НовыйДок, ПараметрыЗаполнения);
    
    // Ручное заполнение реквизитов, если штатные методы не подходят
    НовыйДок.СпособВыплаты = Справочники.СпособыВыплатыЗарплаты.Зарплата;
    НовыйДок.ПроцентВыплаты = 100;
    
    НоваяСтрока = НовыйДок.Зарплата.Добавить();
    НоваяСтрока.Сотрудник = Справочники.Сотрудники.НайтиПоКоду("001");
    НоваяСтрока.КВыплате = 50000;
    
    НовыйДок.Записать(РежимЗаписиДокумента.Запись);
    
КонецПроцедуры

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

Решение №2: Открытие формы с передачей параметров заполнения

Если же ваша цель — открыть пользователю готовую, предзаполненную форму нового документа, то не нужно пытаться программно нажимать кнопки или подменять контекст. В системе 1С предусмотрен штатный механизм передачи параметров при открытии формы.

Рассмотрим, как передать параметры так, чтобы форма документа сама их подхватила и обработала в процедуре ОбработкаЗаполнения или ПриСозданииНаСервере:


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

При использовании этого метода произойдет следующее:

  1. Система создаст новый объект в памяти.
  2. Вызовется процедура ОбработкаЗаполнения в модуле объекта, куда придут ваши ЗначенияЗаполнения.
  3. После этого будет создана форма и вызвана процедура ПриСозданииНаСервере самой формы.
  4. Внутри ПриСозданииНаСервере штатный код конфигурации (например, ВзаиморасчетыССотрудникамиФормы.ВедомостьПриСозданииНаСервере) отработает корректно, так как у него будет доступ к реальному объекту ЭтаФорма и его свойствам Параметры.

Решение №3: Работа через ДанныеФормы на сервере

Бывают ситуации, когда вы уже находитесь в контексте формы внешней обработки и хотите программно модифицировать данные формы другого объекта. Посмотрим, как это сделать через ДанныеФормыВЗначение и обратно, но помните, что это не даст вам возможности вызвать методы, требующие саму форму.


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

Резюме: Главная ошибка автора заключалась в попытке передать «муляж» формы в процедуры, предназначенные для управления элементами интерфейса. Если вам нужно создать документ — работайте с ДокументОбъект в серверном модуле. Если нужно показать документ пользователю — используйте ОткрытьФорму с параметрами заполнения. Прямой вызов процедур типа ПриСозданииНаСервере извне является нарушением принципов разработки в управляемом приложении.

← На главную