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