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

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

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

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

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

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

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

Проверка через свойство Проведен у объекта документа

Если у вас есть объект документа (тип ДокументОбъект), полученный методом ПолучитьОбъект() или созданный в обработчике, проверка выполняется обращением к свойству Проведен. Это булево значение: Истина — документ проведён, Ложь — не проведён или помечен на удаление.

ДокументОбъект = СсылкаНаДокумент.ПолучитьОбъект();

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

Сообщить("Документ проведён");

Иначе

Сообщить("Документ не проведён");

КонецЕсли;

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

Отдельный случай — проверка внутри обработчиков самого объекта (например, в ОбработкаПроведения или ПередЗаписью). Там обращайтесь к свойству напрямую: ЭтотОбъект.Проведен или просто Проведен. Но учтите, что в момент ПередЗаписью с режимом проведения признак может ещё не отражать итоговое состояние — надёжнее анализировать параметр РежимЗаписи.

Проверка через ссылку без получения объекта

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

Если СсылкаНаДокумент.Проведен Тогда

// документ проведён в базе данных

КонецЕсли;

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

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

Массовая проверка через запрос

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

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

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

"ВЫБРАТЬ

| РеализацияТоваровУслуг.Ссылка КАК Ссылка

|ИЗ

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

|ГДЕ

| РеализацияТоваровУслуг.Проведен

| И РеализацияТоваровУслуг.Дата МЕЖДУ &НачалоПериода И &КонецПериода";

Запрос.УстановитьПараметр("НачалоПериода", НачалоДня(НачалоПериода));

Запрос.УстановитьПараметр("КонецПериода", КонецДня(КонецПериода));

Результат = Запрос.Выполнить().Выгрузить();

Через запрос удобно сразу комбинировать условия: например, исключить помеченные на удаление, отобрать по организации или контрагенту. Помеченный на удаление документ всегда имеет Проведен = Ложь, но для ясности логики лучше явно проверять и ПометкаУдаления, если эти состояния для вас различны.

Ещё один приём — проверка существования проведённого документа по условию без выборки всех данных: используйте ВЫБРАТЬ ПЕРВЫЕ 1 и проверяйте Результат.Пустой(). Это стандартный способ быстро ответить на вопрос «есть ли хотя бы один проведённый документ, удовлетворяющий условию».

bsl
Запрос = Новый Запрос("ВЫБРАТЬ ПЕРВЫЕ 1 Истина ИЗ Документ.ПриходнаяНакладная ГДЕ Проведен И Контрагент = &Контрагент");
Запрос.УстановитьПараметр("Контрагент", КонтрагентСсылка);
ЕстьПроведенные = НЕ Запрос.Выполнить().Пустой();

Проверка в форме документа и на клиенте

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

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

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

Порядок действий при выборе способа
  1. 1
    Определите, что у вас есть: объект, ссылка или список ссылок
  2. 2
    Если объект уже получен — читайте свойство Проведен напрямую
  3. 3
    Если одна ссылка и объект не нужен — используйте Ссылка.Проведен
  4. 4
    Если много документов или сложные условия — напишите запрос с полем Проведен
  5. 5
    Проверьте результат: для проведённого документа значение Истина, для непроведённого и помеченного — Ложь

Чем проверка отличается от попытки проведения

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

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

Также учитывайте, что у документа может быть запрещено проведение на уровне конфигурации (свойство «Проведение» в метаданных установлено в «Запретить»). У таких документов поле Проведен существует, но всегда равно Ложь, и попытка проведения вызовет ошибку.

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

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

Вторая ошибка — путать Проведен и ПометкаУдаления. Помеченный документ не проведён, но не каждый непроведённый документ помечен. Если бизнес-логика требует различать эти состояния, проверяйте оба поля явно.

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

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

Сравнение способов и контроль результата

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

СпособКогда применятьСтоимостьОграничение
Объект.ПроведенОбъект уже получен для других действийБесплатно, данные в памятиТребует ПолучитьОбъект()
Ссылка.ПроведенРазовая проверка одной ссылкиОдин запрос к базеНе для циклов
Запрос с полем ПроведенМассовая проверка, отборы, отчётыОдин запрос на всю выборкуТолько данные из базы, не из формы
Объект.Проведен в формеЛогика интерфейса, доступность кнопокБез серверного вызоваМожет отличаться от базы при параллельном редактировании
Контрольные точки

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

Значение свойства Проведен
Норма

Истина — документ проведён и делает движения

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

Ложь, хотя в интерфейсе документ выглядит проведённым — проверьте, ту ли ссылку читаете

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

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

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

Цикл с ПолучитьОбъект() или Ссылка.Проведен выполняется десятки секунд

Согласованность с интерфейсом
Норма

Результат проверки совпадает с пиктограммой документа в списке

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

Расхождение — вероятно, читается устаревший объект или другая ссылка

После выбора способа обязательно проверьте код на трёх состояниях: проведённый документ, непроведённый и помеченный на удаление. Такой минимальный набор покрывает все варианты значения признака и позволяет сразу увидеть ошибки в логике условий.

Часто задаваемые вопросы

Можно ли проверить проведение документа без запроса и без ПолучитьОбъект()?

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

Почему Проведен возвращает Ложь у документа, который выглядит проведённым?

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

Как проверить, проведён ли документ, найденный по номеру?

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

Что возвращает Проведен у помеченного на удаление документа?

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

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

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

Работает ли проверка Проведен в фоновом задании?

Да, в фоновых заданиях и на сервере доступны все способы: свойство объекта, обращение через ссылку и запросы. Недоступна только работа с данными формы, поскольку формы в фоновом контексте не существует.

Итог

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

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