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

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

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

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

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

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

Ниже разобраны оба способа с примерами кода, особенности работы с табличными частями, проверка результата и типичные ошибки, которые приводят к потере данных или непроведённым документам.

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

Механизм строится на трёх элементах. Первый — свойство документа «Вводится на основании» в конфигураторе, которое определяет, какие типы документов могут служить основанием. Второй — свойство «Является основанием для» у документа-источника. Третий — процедура ОбработкаЗаполнения в модуле объекта документа, которая выполняется при интерактивном вводе на основании и при программном вызове метода Заполнить().

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

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

Способ 1: типовое заполнение через метод Заполнить()

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

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

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

НовыйДок.Заполнить(ЗаказСсылка); // ЗаказСсылка — ссылка на документ-основание

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

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

Способ 2: ручное заполнение реквизитов в коде

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

НовыйДок = Документы.ПриходныйКассовыйОрдер.СоздатьДокумент();

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

НовыйДок.Организация = Основание.Организация;

НовыйДок.Контрагент = Основание.Контрагент;

НовыйДок.ДокументОснование = Основание.Ссылка;

НовыйДок.СуммаДокумента = СуммаКОплате;

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

Копирование табличной части выполняется перебором строк основания с добавлением строк в новый документ. Прямое присваивание табличной части целиком (НовыйДок.Товары = Основание.Товары) не работает — табличные части сравниваются и копируются только построчно или через Выгрузить() / Загрузить().

Для Каждого СтрокаОснования Из Основание.Товары Цикл

Если СтрокаОснования.Отменено Тогда

Продолжить;

КонецЕсли;

НоваяСтрока = НовыйДок.Товары.Добавить();

ЗаполнитьЗначенияСвойств(НоваяСтрока, СтрокаОснования);

КонецЦикла;

Функция ЗаполнитьЗначенияСвойств копирует только совпадающие по именам свойства, поэтому реквизиты, которых нет в документе-приёмнике, будут проигнорированы без ошибки. Это удобно, но опасно: если в приёмнике реквизит называется иначе (например, «КоличествоУпаковок» вместо «Количество»), он молча останется пустым.

Как описать ОбработкаЗаполнения в собственной конфигурации

Если вы разрабатываете собственный документ, логику ввода на основании следует разместить в модуле объекта в процедуре ОбработкаЗаполнения. Первый параметр — ДанныеЗаполнения — это значение, переданное в Заполнить() или выбранное пользователем в меню «Создать на основании».

Процедура ОбработкаЗаполнения(ДанныеЗаполнения, СтандартнаяОбработка)

Если ТипЗнч(ДанныеЗаполнения) = Тип("ДокументСсылка.ЗаказПокупателя") Тогда

Организация = ДанныеЗаполнения.Организация;

Контрагент = ДанныеЗаполнения.Контрагент;

ДокументОснование = ДанныеЗаполнения;

Для Каждого СтрокаТовары Из ДанныеЗаполнения.Товары Цикл

НоваяСтрока = Товары.Добавить();

ЗаполнитьЗначенияСвойств(НоваяСтрока, СтрокаТовары);

КонецЦикла;

КонецЕсли;

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

Обращение к реквизитам ДанныеЗаполнения выполняется через точку, что приводит к неявному запросу к базе данных для каждого реквизита. При массовом создании документов лучше один раз выгрузить данные основания запросом и работать с выборкой — это заметно быстрее.

В типовых конфигурациях (УТ, ERP, БП) обработка заполнения уже реализована, и менять её в модуле объекта не стоит — это усложнит обновление. Для доработки логики используйте расширение конфигурации с аннотацией &После("ОбработкаЗаполнения") или подписку на событие ОбработкаЗаполнения.
ПЗ
Практическое замечание

Запись, проведение и проверка результата

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

Попытка

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

Исключение

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

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

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

ВызватьИсключение;

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

Признаки корректно созданного документа: ссылка не пустая (НовыйДок.Ссылка.Пустая() = Ложь), документ проведён, в журнале он отображается с нужной датой, а в форме основания в панели «Связанные документы» появилась связь. Если связь не отображается — проверьте, заполнен ли реквизит-основание и входят ли оба документа в соответствующий критерий отбора.

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

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

Ссылка на документ
Норма

Ссылка не пустая, документ открывается из журнала

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

Пустая ссылка — запись не выполнена или отменена транзакцией

Реквизит-основание
Норма

Поле ДокументОснование заполнено ссылкой на источник

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

Поле пустое — связь не установлена, структура подчинённости не покажет документ

Движения документа
Норма

После проведения есть записи в регистрах

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

Движений нет — проведение завершилось с ошибкой или не выполнялось

Массовое создание документов на основании

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

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

Порядок массового создания
  1. 1
    Запросом выберите основания, по которым ещё нет дочерних документов
  2. 2
    В цикле создайте документ, вызовите Заполнить(Основание), установите дату
  3. 3
    Проверьте заполненность обязательных реквизитов и табличных частей
  4. 4
    Запишите документ в попытке; ошибку зафиксируйте и продолжите цикл
  5. 5
    После цикла выведите отчёт: сколько создано, сколько пропущено и почему

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

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

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

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

Частые вопросы

Можно ли создать документ на основании, если в конфигураторе не настроено «Вводится на основании»?

Да. Настройка в конфигураторе влияет только на интерактивное меню «Создать на основании» и стандартную обработку заполнения. Программно вы можете создать объект документа и заполнить его данными любого источника вручную или через собственную процедуру.

Чем Заполнить() отличается от ОбработкаЗаполнения?

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

Как создать один документ на основании нескольких документов?

Штатный механизм работает с одним основанием. Для нескольких источников создайте документ, вызовите Заполнить() по первому основанию, а строки остальных добавьте в цикле вручную. Либо реализуйте собственную процедуру заполнения, принимающую массив ссылок.

Почему после Заполнить() документ пустой?

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

Как создать документ на основании в фоновом задании?

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

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

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

Итог

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

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