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

Программист 1С v8.3 (Управляемые формы) 1С:Управление торговлей Управленческий учет IT и автоматизация бизнеса
← На главную

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

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

Прежде чем мы приступим к написанию кода, определимся с подходами. Существует два основных сценария создания документа:

  1. Создание "с нуля": мы создаем новый пустой объект и вручную заполняем каждый реквизит.
  2. Создание "на основании": мы используем механизмы платформы для автоматического переноса данных из документа-основания.

Разберем оба варианта, так как они дополняют друг друга.

Вариант 1: Создание документа "с нуля"

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

Проанализируем базовый алгоритм действий:

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

Рассмотрим пример кода для создания документа "Реализация товаров и услуг":


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

// Устанавливаем дату. Если не установить время, оно будет 00:00:00
НовыйДокумент.Дата = ТекущаяДата();

// Заполняем основные реквизиты шапки
// Обратите внимание: ссылки должны быть предварительно найдены или переданы
НовыйДокумент.Организация = Справочники.Организации.НайтиПоНаименованию("Основная фирма");
НовыйДокумент.Контрагент = СсылкаНаКонтрагента; 
НовыйДокумент.Склад = СсылкаНаСклад;
НовыйДокумент.ВалютаДокумента = Справочники.Валюты.НайтиПоКоду("643"); // Рубли

// Заполняем комментарий для отладки
НовыйДокумент.Комментарий = "Создан программно " + Строка(ТекущаяДата());

Важный нюанс: Не пытайтесь присвоить номер документа вручную (НовыйДокумент.Номер = ...), если в этом нет жесткой необходимости. Платформа 1С использует механизм автонумерации, и принудительное присвоение может сбить последовательность номеров. Номер будет присвоен автоматически в момент вызова метода Записать().

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

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


// Добавляем новую строку в табличную часть
НоваяСтрока = НовыйДокумент.Товары.Добавить();

// Заполняем данные строки
НоваяСтрока.Номенклатура = СсылкаНаТовар;
НоваяСтрока.Количество = 10;
НоваяСтрока.Цена = 1000;
НоваяСтрока.Сумма = НоваяСтрока.Количество * НоваяСтрока.Цена;
НоваяСтрока.СтавкаНДС = Перечисления.СтавкиНДС.НДС20;
НоваяСтрока.СуммаНДС = НоваяСтрока.Сумма * 20 / 120; // Примерный расчет

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


// Предположим, ТЗ_Товары - это таблица значений с нужными данными
НовыйДокумент.Товары.Загрузить(ТЗ_Товары);

Вариант 2: Создание документа на основании (метод Заполнить)

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

Посмотрим, как это выглядит на практике. Допустим, нам нужно создать "Реализацию" на основании "Заказа клиента".


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

// 2. Вызываем метод Заполнить, передавая ссылку на основание
// СсылкаНаЗаказ - это ссылка на документ "Заказ клиента"
ДокРеализация.Заполнить(СсылкаНаЗаказ);

// 3. При необходимости корректируем дату, так как она может заполниться датой заказа
ДокРеализация.Дата = ТекущаяДата();

// В этот момент большинство реквизитов (Контрагент, Организация, Товары) уже заполнены

Использование метода Заполнить() гарантирует, что мы не пропустим важную бизнес-логику, заложенную разработчиками конфигурации (например, подстановку договоров, счетов учета или пересчет валют).

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

Созданный объект находится в памяти. Чтобы он появился в базе данных, его нужно записать. Для этого используется метод Записать(). У этого метода есть параметры, определяющие режим записи (просто запись, проведение или отмена проведения).

Рассмотрим режимы записи через системное перечисление РежимЗаписиДокумента:

Код для записи и проведения:


Попытка
    // Пытаемся провести документ
    НовыйДокумент.Записать(РежимЗаписиДокумента.Проведение);
    Сообщить("Документ успешно создан и проведен: " + НовыйДокумент.Ссылка);
Исключение
    // Если возникла ошибка (например, не хватает товара на складе), выводим сообщение
    Сообщить("Не удалось провести документ: " + ОписаниеОшибки());
    
    // Можно попробовать просто записать, без проведения, чтобы не терять данные
    Попытка
        НовыйДокумент.Записать(РежимЗаписиДокумента.Запись);
        Сообщить("Документ сохранен как черновик.");
    Исключение
        Сообщить("Критическая ошибка записи.");
    КонецПопытки;
КонецПопытки;

Обработка ошибок и транзакции

При массовом программном создании документов критически важно использовать транзакции. Если мы создаем 100 документов, и на 99-м происходит сбой, использование транзакции позволит откатить все изменения, чтобы база не осталась в рассогласованном состоянии. Либо, наоборот, мы можем фиксировать каждый документ в отдельной транзакции.

Посмотрим на пример безопасного создания документов:


НачатьТранзакцию();
Попытка
    
    // ... здесь код создания и заполнения документа ...
    
    НовыйДокумент.Записать(РежимЗаписиДокумента.Проведение);
    
    ЗафиксироватьТранзакцию();
    
Исключение
    ОтменитьТранзакцию();
    Сообщить("Ошибка при создании документа: " + ОписаниеОшибки());
КонецПопытки;

Дополнительные полезные методы и свойства

При работе с документами полезно знать еще несколько свойств и методов объекта:

  1. ОбменДанными.Загрузка = Истина
    Если установить это свойство в Истина перед записью, платформа отключит большинство проверок (например, проверку заполнения обязательных реквизитов) и не будет вызывать некоторые обработчики событий. Это полезно при переносе данных из других баз, когда нам нужно записать объект "как есть", даже если он не совсем корректен с точки зрения текущей логики.

    
    НовыйДокумент.ОбменДанными.Загрузка = Истина;
    НовыйДокумент.Записать(РежимЗаписиДокумента.Запись);
    
  2. УстановитьНовоеВремя()
    Если мы создаем документ "задним числом" или в текущем дне, но хотим, чтобы он встал в конец дня (или в конкретную позицию относительно других документов), можно использовать этот метод. Он автоматически подбирает время внутри даты документа так, чтобы документ встал последним.

    
    НовыйДокумент.Дата = ТекущаяДата();
    НовыйДокумент.УстановитьНовоеВремя(); // Время сдвинется, чтобы не конфликтовать с существующими
    

Рекомендации по оптимизации

При программном создании большого количества документов учитывайте следующие моменты:

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

← На главную