К статье
Практический материал

Разработка и Конфигурация · 12 мин

Как программно ввести документ на основании в 1С

Как в 1С программно создать документ на основании другого: методы ВвестиНаОсновании, обработчики заполнения, примеры кода и типичные ошибки разработчиков.

Ввод на основании — один из базовых механизмов связи документов в 1С: он позволяет создать новый документ, автоматически заполнив его реквизиты и табличные части данными документа-основания. В пользовательском режиме это делается кнопкой «Создать на основании», но в прикладном коде часто требуется сделать то же самое программно — в регламентных заданиях, обработках, обменах и расширениях.

Программное создание на основании сводится к трём шагам: создать объект документа, заполнить его по данным основания (обычно через стандартный обработчик заполнения) и записать. При этом важно понимать, как именно конфигурация реализует заполнение — через обработчик ОбработкаЗаполнения в модуле объекта или через централизованные процедуры, — иначе основание не проставится и связь документов потеряется.

Ниже разобраны оба подхода для обычных и управляемых форм, работа с критериями отбора, проверка результата и типичные ошибки, из-за которых программно созданные документы «теряют» связь с основанием или ломают проведение.

Как устроен механизм ввода на основании в 1С

Когда пользователь нажимает «Создать на основании», платформа создаёт новый объект и вызывает у него обработчик ОбработкаЗаполнения, передавая туда ссылку на основание в параметре ДанныеЗаполнения. Весь перенос данных — реквизитов шапки, табличных частей, контрагентов, договоров — выполняется кодом этого обработчика, написанным разработчиком конфигурации.

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

Дополнительно связь документов фиксируется в критериях отбора (например, «Связанные документы» или «Структура подчинённости»), которые строятся по реквизитам типа «ДокументСсылка». Если при заполнении реквизит основания не проставлен, документ будет создан, но в структуре подчинённости не появится.

Базовый способ: СоздатьДокумент и метод Заполнить

Универсальный и рекомендуемый подход — создать объект через менеджер документа и вызвать метод Заполнить(), передав ему ссылку на основание. Тогда отработает тот же код заполнения, что и при интерактивном вводе, и результат будет идентичен действиям пользователя.

НовыйДок = Документы.РеализацияТоваровУслуг.СоздатьДокумент();

НовыйДок.Заполнить(ЗаказСсылка); // вызовет ОбработкаЗаполнения

НовыйДок.Дата = ТекущаяДатаСеанса();

НовыйДок.Записать(РежимЗаписиДокумента.Проведение);

Обратите внимание: метод Заполнить() не устанавливает дату документа — её нужно проставить явно, иначе документ запишется с пустой датой или датой по умолчанию, что может нарушить нумерацию и последовательность проведения. Также стоит проставлять реквизиты, которые обработчик заполнения не трогает: ответственного, подразделение, комментарий.

Если нужно создать документ без проведения, используйте Записать() без параметров или с режимом РежимЗаписиДокумента.Запись. Проведение сразу при создании оправдано, только когда вы уверены в корректности всех данных — например, в полностью автоматических сценариях с проверенными основаниями.

Порядок программного ввода на основании
  1. 1
    Получите ссылку на документ-основание и проверьте, что он существует и не помечен на удаление
  2. 2
    Создайте новый объект: Документы.<Имя>.СоздатьДокумент()
  3. 3
    Вызовите НовыйДок.Заполнить(СсылкаНаОснование)
  4. 4
    Установите дату, ответственного и прочие обязательные реквизиты
  5. 5
    Проверьте заполнение обязательных полей и табличных частей
  6. 6
    Запишите документ: Записать() или Записать(РежимЗаписиДокумента.Проведение)
  7. 7
    Проверьте появление документа в структуре подчинённости основания

Ввод на основании в конфигурациях на обычных формах

В старых конфигурациях на обычных формах (УПП, УТ 10, БП 1.6/2.0) встречается другой исторический подход — процедуры вида ЗаполнитьПоОснованию или прямое копирование реквизитов в модуле объекта. Обработчик ОбработкаЗаполнения там тоже существует, поэтому метод Заполнить() работает так же.

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

Если логика оказалась в форме, корректное решение — перенести её в обработчик ОбработкаЗаполнения модуля объекта, а не дублировать в своей обработке. Иначе при каждом обновлении конфигурации придётся синхронизировать две копии одного алгоритма.

Заполнение нескольких документов и массовые сценарии

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

Запрос = Новый Запрос;

Запрос.Текст =

"ВЫБРАТЬ

| Заказ.Ссылка КАК Основание,

| Реализация.Ссылка КАК УжеВведена

|ИЗ

| Документ.ЗаказПокупателя КАК Заказ

| ЛЕВОЕ СОЕДИНЕНИЕ Документ.РеализацияТоваровУслуг КАК Реализация

| ПО Реализация.ЗаказПокупателя = Заказ.Ссылка

|ГДЕ

| Заказ.Проведен

| И Реализация.Ссылка ЕСТЬ NULL";

Выборка = Запрос.Выполнить().Выбрать();

Пока Выборка.Следующий() Цикл

Попытка

НовыйДок = Документы.РеализацияТоваровУслуг.СоздатьДокумент();

НовыйДок.Заполнить(Выборка.Основание);

НовыйДок.Дата = ТекущаяДатаСеанса();

НовыйДок.Записать(РежимЗаписиДокумента.Проведение);

Исключение

ЗаписьЖурналаРегистрации("АвтовводНаОсновании",

УровеньЖурналаРегистрации.Ошибка, , ,

ОписаниеОшибки());

КонецПопытки;

КонецЦикла;

Проверка «уже введён» через левое соединение защищает от дублей при повторном запуске обработки. Запись ошибок в журнал регистрации вместо прерывания цикла позволяет обработать остальные основания и разобрать проблемные документы отдельно.

Особенности управляемых форм и клиент-серверного вызова

Если программный ввод на основании нужно инициировать из управляемой формы (например, по своей кнопке), код создания документа должен выполняться на сервере. Типовой приём — кнопка вызывает серверную процедуру общего модуля или формы с директивой &НаСервере, которая создаёт документ и возвращает ссылку, после чего клиент открывает форму нового документа.

&НаСервере

Функция СоздатьРеализациюНаСервере(Основание)

НовыйДок = Документы.РеализацияТоваровУслуг.СоздатьДокумент();

НовыйДок.Заполнить(Основание);

НовыйДок.Дата = ТекущаяДатаСеанса();

НовыйДок.Записать();

Возврат НовыйДок.Ссылка;

КонецФункции

&НаКлиенте

Процедура СоздатьРеализацию(Команда)

Ссылка = СоздатьРеализациюНаСервере(Объект.Ссылка);

ОткрытьЗначение(Ссылка);

КонецПроцедуры

Альтернатива — не записывать документ сразу, а открыть форму нового документа с параметром Основание: платформа сама вызовет обработчик заполнения, и пользователь сможет проверить и скорректировать данные до записи. Это безопаснее для сценариев, где требуется контроль человеком.

Два подхода к созданию документа

Записать сразу на сервере

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

Открыть форму с параметром Основание

Подходит для интерактивной работы: данные заполняются, но пользователь проверяет их перед записью. Ограничение: не работает без участия пользователя.

Проверка результата и связь с основанием

После записи убедитесь, что документ не просто создан, а правильно связан с основанием. Откройте структуру подчинённости у документа-основания: новый документ должен в ней отображаться. Если его там нет — значит, реквизит основания не заполнен, и проблема в обработчике заполнения или в том, что вызов Заполнить() был пропущен.

Дополнительно проверьте ключевые реквизиты: организацию, контрагента, договор, валюту и табличные части. Сравнение с документом, созданным интерактивно по тому же основанию, — самый надёжный способ убедиться, что программный ввод эквивалентен ручному.

Контрольные точки

Как проверить результат

Документ в структуре подчинённости основания
Норма

Новый документ виден в списке связанных

Тревожный признак

Документа нет — не заполнен реквизит основания

Табличные части
Норма

Состав и количество совпадают с основанием или ожидаемым остатком

Тревожный признак

Табличная часть пуста или содержит лишние строки

Проведение
Норма

Документ проводится без ошибок, движения корректны

Тревожный признак

Ошибки проведения по незаполненным реквизитам

Ключевые реквизиты шапки
Норма

Организация, контрагент, договор совпадают с основанием

Тревожный признак

Реквизиты пустые или заполнены значениями по умолчанию

Типичные ошибки и ограничения

Самая частая ошибка — создание документа без вызова Заполнить() с ручным копированием пары реквизитов. Такой документ выглядит заполненным, но не попадает в критерии отбора, не учитывается в проверках «введено на основании» в типовых конфигурациях и ломает цепочки взаиморасчётов.

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

Ещё одно ограничение: обработчик заполнения в типовой конфигурации может проверять функциональные опции, статус основания или остатки к отгрузке. Если основание не удовлетворяет условиям, документ создастся пустым или частично заполненным — это нормальное поведение, а не ошибка вашего кода.

Типичные ошибки
01
Ручное копирование реквизитов вместо вызова Заполнить() — теряется связь с основанием и логика типовой конфигурации
02
Отсутствие установки даты документа — нарушается нумерация и последовательность проведения
03
Нет проверки на уже введённые документы — при повторном запуске обработки появляются дубли
04
Проведение в цикле без Попытка/Исключение — одна ошибка останавливает обработку всех оснований
05
Игнорирование прав служебного пользователя регламентного задания — тихие сбои записи

FAQ

Чем отличается метод Заполнить() от прямого присвоения реквизитов?

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

Можно ли программно ввести на основании несколько документов сразу?

Да, стандартный обработчик заполнения умеет работать с массивом оснований, если это предусмотрено конфигурацией: передайте в Заполнить() массив ссылок. В типовых конфигурациях так реализован, например, ввод одной реализации по нескольким заказам. Если обработчик массив не поддерживает, потребуется доработка.

Почему программно созданный документ не виден в структуре подчинённости?

Структура подчинённости строится по реквизитам, содержащим ссылку на основание. Если документ создан без вызова Заполнить() или обработчик не проставил реквизит основания, связи нет. Проверьте, что реквизит типа «ДокументСсылка» заполнен и включён в соответствующий критерий отбора.

Как создать документ на основании из внешней обработки?

Точно так же, как из любого серверного кода: получите ссылку на основание, вызовите СоздатьДокумент(), Заполнить(), установите дату и запишите. Внешняя обработка не накладывает ограничений, но запускается под правами текущего пользователя — у него должны быть права на добавление целевого документа.

Безопасно ли сразу проводить документ при программном создании?

Безопасно только в отлаженных автоматических сценариях с проверенными данными. В остальных случаях лучше записывать без проведения и давать пользователю или отдельной проверке возможность убедиться в корректности — отмена проведения массово созданных ошибочных документов трудоёмка.

Итог

Что важно запомнить

Программный ввод на основании выполняется связкой СоздатьДокумент() → Заполнить(Основание) → установка даты → Записать(). Метод Заполнить() гарантирует тот же результат, что и кнопка «Создать на основании», и сохраняет связь документов. В массовых сценариях обязательны проверка дублей, обработка ошибок и тест на копии базы.