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

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

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

Как в 1С проверить, что документ успешно записан: методы Записать, Записывается, ПроверитьЗаполнение, обработка исключений. Примеры кода на встроенном языке.

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

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

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

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

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

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

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

Проверка через Попытка/Исключение — базовый приём

Самый распространённый способ убедиться, что документ записан, — перехватить исключение. Если исключения не было, запись прошла; если было — получаем текст ошибки и решаем, что делать дальше.

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

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

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

// ... заполнение реквизитов и табличных частей

Попытка

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

ДокументЗаписан = Истина;

Исключение

ДокументЗаписан = Ложь;

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

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

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

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

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

Проверка заполнения до записи

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

Если НЕ НовыйДок.ПроверитьЗаполнение() Тогда

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

Возврат;

КонецЕсли;

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

Такое разделение полезно ещё и тем, что позволяет различить классы ошибок: «документ не прошёл проверку данных» и «документ не удалось физически записать». В первом случае нужно исправлять данные, во втором — разбираться с блокировками, правами или кодом подписок.

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

Проверка по ссылке после записи

Косвенный, но надёжный признак успешной записи нового документа — заполненная ссылка. У только что созданного объекта до записи ссылка пустая (точнее, не установлена); после успешной записи платформа присваивает объекту ссылку, и она становится доступна через свойство Ссылка.

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

Если НовыйДок.Ссылка.Пустая() Тогда

// Запись не выполнена

Иначе

// Документ записан, ссылка получена

КонецЕсли;

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

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

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

"ВЫБРАТЬ ПЕРВЫЕ 1

| Реализация.Ссылка КАК Ссылка

|ИЗ

| Документ.РеализацияТоваровУслуг КАК Реализация

|ГДЕ

| Реализация.Ссылка = &Ссылка";

Запрос.УстановитьПараметр("Ссылка", ПроверяемаяСсылка);

Если Запрос.Выполнить().Пустой() Тогда

// Документа в базе нет

КонецЕсли;

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

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

ДокОбъект.Записать(РежимЗаписиДокумента.Проведение,

РежимПроведенияДокумента.Оперативный);

Если НЕ ДокОбъект.Проведен Тогда

// Проведение не выполнено — анализируем причины

КонецЕсли;

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

Порядок действий
  1. 1
    Заполните объект документа и вызовите ПроверитьЗаполнение() — отсеките ошибки данных
  2. 2
    Выполните Записать() внутри Попытка/Исключение с нужным режимом записи
  3. 3
    При исключении зафиксируйте ОписаниеОшибки() в журнале регистрации и прервите сценарий
  4. 4
    После успешной записи убедитесь, что Ссылка не пустая
  5. 5
    Если требуется проведение — проверьте свойство Проведен
  6. 6
    При записи в транзакции финальную проверку существования выполните после фиксации транзакции

Диагностика причин, почему документ не записался

Когда проверка показала, что документ не записан, следующий шаг — определить причину. Текст исключения в большинстве случаев содержит прямое указание: конфликт блокировки, нарушение прав доступа, отказ в обработчике, ошибка проверки заполнения.

Текст или признак ошибкиВероятная причинаЧто делать
«Конфликт блокировки при выполнении транзакции»Документ или связанные данные редактируются другим сеансомПовторить попытку позже, сократить длительность транзакции
«Нарушение прав доступа»У пользователя нет прав на запись или проведениеПроверить роли и RLS, выполнить от имени привилегированного задания
Сообщение из подписки на событиеОтказ в обработчике ПередЗаписью/ПриЗаписиАнализировать код подписки, проверить входные данные
«Поле ... не заполнено»Не пройдена проверка заполненияЗаполнить обязательные реквизиты до записи
Ошибок нет, но документа в базе нетОткат транзакции вызывающим кодомПроверить логику НачатьТранзакцию/ОтменитьТранзакцию

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

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

Проверка с клиентской стороны и в управляемых формах

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

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

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

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

Метод Записать() не выдал ошибку — значит ли это, что документ точно в базе?

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

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

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

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

Используйте запрос с конструкцией ПЕРВЫЕ 1 по таблице документа с условием по ссылке — если результат пустой, объекта нет. В конфигурациях на базе Библиотеки стандартных подсистем есть готовая функция ОбщегоНазначения.СсылкаСуществует(), которая делает то же самое.

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

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

Как проверить запись документа при загрузке через ОбменДанными.Загрузка?

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

Что делать при ошибке «Конфликт блокировки» в регламентном задании?

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

Итог

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

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