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