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

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

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

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

Создание объекта документа

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

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


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

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

Заполнение реквизитов шапки

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

Дата документа является критически важным полем. Если мы не заполним её явно, платформа подставит пустую дату или начало текущей сессии (в зависимости от контекста), что может привести к ошибкам. Рассмотрим пример заполнения шапки:


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

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

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

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

Работа с табличной частью

Теперь перейдем к более сложной части — заполнению списка товаров. У документа есть табличная часть, которая обычно называется Товары. Нам нужно добавить в неё новые строки.

Для добавления строки используем метод Добавить() на коллекции строк табличной части. Этот метод возвращает объект строки, свойства которой мы затем заполняем. Разберем это на примере:


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

// Заполняем данные строки
НоваяСтрока.Номенклатура = Справочники.Номенклатура.НайтиПоКоду("Арт-001");
НоваяСтрока.Количество = 10;
НоваяСтрока.Цена = 1500;
НоваяСтрока.Сумма = НоваяСтрока.Количество * НоваяСтрока.Цена;

// Если в документе есть автоматический пересчет (например, НДС), 
// иногда требуется вызывать экспортные процедуры модуля объекта, 
// но при программном создании часто надежнее рассчитать все явно.
НоваяСтрока.СтавкаНДС = Перечисления.СтавкиНДС.НДС20;
НоваяСтрока.СуммаНДС = НоваяСтрока.Сумма * 20 / 120; 

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


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

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

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

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

  1. Простая запись: РежимЗаписиДокумента.Запись. Документ сохраняется, но не влияет на остатки.
  2. Проведение: РежимЗаписиДокумента.Проведение. Документ сохраняется и делает движения.
  3. Отмена проведения: РежимЗаписиДокумента.ОтменаПроведения. Если документ был проведен, движения очищаются.

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


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

Оптимизация и важные нюансы

Проанализируем несколько продвинутых моментов, которые отличают код опытного программиста от новичка. Эти знания мы почерпнули из анализа дополнительных источников и документации.

1. Режим загрузки данных

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

Установив это свойство в Истина, мы говорим платформе: "Я знаю, что делаю, запиши данные как есть, без лишних проверок". Однако будьте осторожны: движения по регистрам в этом случае тоже могут не сформироваться автоматически, если логика проведения завязана на это свойство.


НовыйДокумент.ОбменДанными.Загрузка = Истина; 
НовыйДокумент.Записать(РежимЗаписиДокумента.Запись); 
// При таком режиме обычно используют просто Запись, 
// а движения формируют отдельно или полагаются на модуль объекта.

2. Блокировка и транзакции

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


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

3. Установка времени документа

При программном создании часто возникает проблема, когда документы создаются в 00:00:00, если указать только дату. Чтобы документы выстраивались в хронологическом порядке, используйте метод УстановитьВремя() или явно задавайте время в поле Дата. Для новых документов также полезен метод УстановитьНовыйНомер(), если автонумерация не срабатывает автоматически так, как вам нужно (обычно она срабатывает в момент записи).


НовыйДокумент.УстановитьНовыйНомер(); // Генерирует код/номер по префиксу организации

Итог

Мы рассмотрели полный цикл программного создания документа в 1С. Давайте закрепим основные этапы:

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

Используя эти методы, вы сможете создавать надежные алгоритмы обработки данных, которые корректно взаимодействуют с логикой конфигурации.

← На главную