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

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

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

Разбираем, как программно создать документ в 1С 8: объект ДокументОбъект, заполнение реквизитов и табличных частей, запись, проведение, ошибки и примеры кода.

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

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

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

Как работает объектная модель документов в 1С 8

Каждый вид документа в конфигурации имеет менеджер — объект Документы.<ИмяДокумента>. Через него доступны три ключевых действия: создать новый документ (СоздатьДокумент()), получить объект существующего по ссылке (ПолучитьОбъект()) и найти ссылку по номеру или реквизитам. Для создания нового документа всегда используется первый метод.

Вызов СоздатьДокумент() возвращает объект типа ДокументОбъект, который существует только в памяти. В базе данных записи ещё нет — она появится только после вызова метода Записать(). Это принципиально: если код прервётся до записи, никаких «полудокументов» в базе не останется.

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

Минимальный код создания документа

Простейший сценарий — создать документ, заполнить шапку и записать. Пример для условного документа «РеализацияТоваровУслуг» (имена реквизитов зависят от конкретной конфигурации, их нужно смотреть в конфигураторе):

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

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

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

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

НовыйДок.Договор = Договор;

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

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

Если документ создаётся «задним числом», установите нужную дату вместо текущей. Учтите, что записать документ в закрытый период (при установленной дате запрета изменения данных) не получится — платформа выдаст ошибку на этапе записи.

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

Заполнение табличных частей

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

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

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

НоваяСтрока.Номенклатура = СтрокаДанных.Номенклатура;

НоваяСтрока.Количество = СтрокаДанных.Количество;

НоваяСтрока.Цена = СтрокаДанных.Цена;

НоваяСтрока.Сумма = НоваяСтрока.Количество * НоваяСтрока.Цена;

КонецЦикла;

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

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

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

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

При записи срабатывает обработчик ОбработкаПроверкиЗаполнения, если он определён в модуле объекта. Если обязательные реквизиты пусты или проверки возвращают отказ, запись прерывается с исключением. Поэтому массовое создание документов стоит оборачивать в попытку и собирать ошибки, а не падать на первом же проблемном объекте:

Попытка

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

Исключение

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

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

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

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

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

Транзакции и массовое создание документов

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

Явная транзакция управляется методами НачатьТранзакцию(), ЗафиксироватьТранзакцию() и ОтменитьТранзакцию(). Один вызов Записать() сам по себе уже выполняется в неявной транзакции, поэтому оборачивать одиночный документ в явную транзакцию обычно не требуется.

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

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

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

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

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

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

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

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

Для копирования существующего документа есть метод Скопировать() у объекта менеджера: Документы.РеализацияТоваровУслуг.Скопировать(СсылкаНаИсходный). Получится новый объект с теми же реквизитами и табличными частями, но без номера и даты — их нужно установить перед записью. Это удобно для документов-шаблонов, которые периодически повторяются.

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

Сравнение вариантов

Ручное заполнение реквизитов

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

Заполнить(Основание)

Штатная логика конфигурации заполняет документ по документу-основанию. Подходит для связанных документов; не работает, если обработчик заполнения в конфигурации не предусмотрен.

Скопировать()

Быстрое создание по образцу существующего документа. Удобно для повторяющихся документов, но требует проверки актуальности цен и остатков.

Проверка результата и типичные ошибки

После записи полезно убедиться, что документ действительно создан и находится в ожидаемом состоянии. Минимальный набор проверок: ссылка не пустая (НовыйДок.Ссылка.Пустая() возвращает Ложь), документ проведён (НовыйДок.Проведен равно Истина, если проводили), номер присвоен. Для массовых загрузок сверяйте количество созданных документов с количеством строк источника.

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

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

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

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

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

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

Ссылка пустая — запись не выполнилась, ищите ошибку в журнале регистрации

Статус проведения
Норма

Проведен = Истина, движения видны в регистрах

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

Документ записан, но не проведён — сработали проверки или исключение при проведении

Номер документа
Норма

Номер присвоен автоматически и уникален

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

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

Типичные ошибки
01
Не установлена дата документа — запись падает с ошибкой, так как дата обязательна
02
Присвоение строки вместо ссылки в реквизит ссылочного типа — ошибка несоответствия типов
03
Ожидание, что цены и ставки НДС подставятся сами — обработчики формы при программном заполнении не вызываются
04
Проведение документов в закрытом периоде — запись блокируется датой запрета изменения данных
05
Создание документов в цикле без обработки исключений — одна ошибка останавливает всю загрузку

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

Итог

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

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

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

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

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

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

Код всегда выполняется от имени текущего сеанса. Чтобы документ создался от нужного пользователя, запускайте фоновое задание или регламентное задание под этим пользователем. Реквизит «Ответственный» при этом можно установить и вручную, если конфигурация его хранит.

Почему документ записывается, но не проводится, и ошибки нет?

Проверьте, не перехвачено ли исключение пустым блоком Попытка/Исключение где-то выше по стеку, и есть ли в модуле объекта обработчик ОбработкаПроведения, который устанавливает Отказ = Истина по своим условиям. Также убедитесь, что вы передаёте именно режим Проведение, а не Запись.

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

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

Можно ли создавать документы через COM или внешнее соединение?

Да, через COM-соединение (V83.COMConnector) или HTTP-сервисы логика та же: в подключённом сеансе доступны те же менеджеры документов и методы. Отличие только в способе установки соединения и в том, что ссылочные типы между соединениями напрямую не передаются — их нужно искать заново по уникальному идентификатору или реквизитам.

Что делать, если при массовом создании растёт время записи каждого следующего документа?

Типичные причины — незакрытые транзакции, накопление объектов в памяти и контроль остатков при проведении. Проверьте, что транзакции фиксируются, ссылки на объекты не копятся в коллекциях, а при больших объёмах рассмотрите запись без проведения с последующим пакетным проведением.