Разработка и Конфигурация · 12 мин
Как программно проверить, проведён ли документ в 1С
Как программно проверить, проведён ли документ 1С: свойство Проведен, запросы к базе, проверка ссылки и типовые ошибки разработчиков.
Проверка того, проведён ли документ, — одна из самых частых задач при доработке конфигураций 1С: она нужна в обработчиках событий, при построении отчётов, в обменах данными и при программном изменении документов. Во встроенном языке для этого существует специальное свойство объекта и поле в запросах, и важно понимать, чем они отличаются и когда какой способ применять.
Главный нюанс состоит в том, что «проведён» — это признак, который хранится в базе данных у каждого документа, но объект в памяти (например, открытый в форме) может отличаться от того, что записано в базе. Поэтому один и тот же вопрос — «проведён ли документ» — имеет разные ответы в зависимости от того, что именно вы проверяете: ссылку, объект или данные формы.
Ниже разобраны все рабочие способы проверки: через свойство Проведен, через запрос, через функциональные опции поведения, а также типичные ошибки, из-за которых проверка даёт неверный результат.
Проверка через свойство Проведен у объекта документа
Если у вас есть объект документа (тип ДокументОбъект), полученный методом ПолучитьОбъект() или созданный в обработчике, проверка выполняется обращением к свойству Проведен. Это булево значение: Истина — документ проведён, Ложь — не проведён или помечен на удаление.
ДокументОбъект = СсылкаНаДокумент.ПолучитьОбъект();
Если ДокументОбъект.Проведен Тогда
Сообщить("Документ проведён");
Иначе
Сообщить("Документ не проведён");
КонецЕсли;
Важно понимать: ПолучитьОбъект() читает данные из базы в память целиком, включая все табличные части. Для простой проверки признака проведения это избыточно и медленно, особенно в цикле. Используйте этот способ только тогда, когда объект вам и так нужен для дальнейших действий — например, для перепроведения или изменения.
Отдельный случай — проверка внутри обработчиков самого объекта (например, в ОбработкаПроведения или ПередЗаписью). Там обращайтесь к свойству напрямую: ЭтотОбъект.Проведен или просто Проведен. Но учтите, что в момент ПередЗаписью с режимом проведения признак может ещё не отражать итоговое состояние — надёжнее анализировать параметр РежимЗаписи.
Проверка через ссылку без получения объекта
Когда объекта нет, а есть только ссылка, проверить признак можно прямо через точку: Ссылка.Проведен. Платформа при таком обращении неявно выполняет запрос к базе данных и возвращает значение поля. Это коротко и удобно для разовой проверки.
Если СсылкаНаДокумент.Проведен Тогда
// документ проведён в базе данных
КонецЕсли;
Преимущество способа — не нужно вызывать ПолучитьОбъект() и вычитывать весь документ. Недостаток — каждое обращение через точку порождает отдельное обращение к базе. Если вы проверяете таким образом десять полей одной ссылки или обходите тысячу ссылок в цикле, получите тысячу отдельных запросов и заметную просадку производительности.
Для одиночной проверки в коде формы или в условии это приемлемый вариант. Для любых массовых операций — переходите к запросу, о котором ниже.
Массовая проверка через запрос
Когда нужно проверить признак проведения у списка документов или выбрать только проведённые документы за период, правильный инструмент — запрос. Поле Проведен доступно в таблице любого документа и индексируется, поэтому выборка работает быстро.
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| РеализацияТоваровУслуг.Ссылка КАК Ссылка
|ИЗ
| Документ.РеализацияТоваровУслуг КАК РеализацияТоваровУслуг
|ГДЕ
| РеализацияТоваровУслуг.Проведен
| И РеализацияТоваровУслуг.Дата МЕЖДУ &НачалоПериода И &КонецПериода";
Запрос.УстановитьПараметр("НачалоПериода", НачалоДня(НачалоПериода));
Запрос.УстановитьПараметр("КонецПериода", КонецДня(КонецПериода));
Результат = Запрос.Выполнить().Выгрузить();
Через запрос удобно сразу комбинировать условия: например, исключить помеченные на удаление, отобрать по организации или контрагенту. Помеченный на удаление документ всегда имеет Проведен = Ложь, но для ясности логики лучше явно проверять и ПометкаУдаления, если эти состояния для вас различны.
Ещё один приём — проверка существования проведённого документа по условию без выборки всех данных: используйте ВЫБРАТЬ ПЕРВЫЕ 1 и проверяйте Результат.Пустой(). Это стандартный способ быстро ответить на вопрос «есть ли хотя бы один проведённый документ, удовлетворяющий условию».
Запрос = Новый Запрос("ВЫБРАТЬ ПЕРВЫЕ 1 Истина ИЗ Документ.ПриходнаяНакладная ГДЕ Проведен И Контрагент = &Контрагент");
Запрос.УстановитьПараметр("Контрагент", КонтрагентСсылка);
ЕстьПроведенные = НЕ Запрос.Выполнить().Пустой();Проверка в форме документа и на клиенте
В модуле формы документа текущий объект доступен через реквизит формы (обычно Объект). Проверка выглядит как Объект.Проведен и отражает состояние редактируемых данных, а не обязательно данных в базе. Если пользователь открыл проведённый документ, нажал «Отменить проведение» в другом окне, а вы читаете старую форму — значения могут разойтись.
На тонком клиенте в управляемых формах обращение Объект.Проведен работает без серверного вызова, потому что данные объекта уже находятся в форме. Это безопасный с точки зрения производительности способ для логики интерфейса: например, чтобы блокировать кнопки или менять заголовок в зависимости от состояния документа.
Если в форме списка нужно показать состояние проведения, не добавляйте код с обращением к ссылкам — в динамическом списке поле Проведен уже доступно, достаточно вывести его в колонку или использовать в условном оформлении.
- 1Определите, что у вас есть: объект, ссылка или список ссылок
- 2Если объект уже получен — читайте свойство Проведен напрямую
- 3Если одна ссылка и объект не нужен — используйте Ссылка.Проведен
- 4Если много документов или сложные условия — напишите запрос с полем Проведен
- 5Проверьте результат: для проведённого документа значение Истина, для непроведённого и помеченного — Ложь
Чем проверка отличается от попытки проведения
Иногда задача формулируется шире: не просто узнать, проведён ли документ, а убедиться, что он может быть проведён. Это разные вещи. Признак Проведен говорит только о текущем состоянии. Чтобы проверить возможность проведения, нужно фактически выполнить ДокументОбъект.Записать(РежимЗаписиДокумента.Проведение) в попытке и перехватить исключение — например, при нехватке остатков на складе проведение завершится ошибкой.
Безопасный шаблон такой проверки — выполнение в транзакции с отменой, если реальное проведение не требуется. Но помните: отмена транзакции откатит и все побочные изменения, а сам подход тяжеловесен. Для предварительной диагностики лучше использовать РежимЗаписиДокумента.Проведение с отловом исключения только там, где это действительно оправдано.
Также учитывайте, что у документа может быть запрещено проведение на уровне конфигурации (свойство «Проведение» в метаданных установлено в «Запретить»). У таких документов поле Проведен существует, но всегда равно Ложь, и попытка проведения вызовет ошибку.
Типичные ошибки и ограничения
Самая частая ошибка — обращение Ссылка.ПолучитьОбъект().Проведен в цикле по тысячам документов. Код работает, но медленно: каждый объект читается целиком. Замените на запрос, и время выполнения сократится на порядки.
Вторая ошибка — путать Проведен и ПометкаУдаления. Помеченный документ не проведён, но не каждый непроведённый документ помечен. Если бизнес-логика требует различать эти состояния, проверяйте оба поля явно.
Третья группа ошибок связана с контекстом выполнения. В фоновых заданиях и внешних соединениях нет формы, поэтому оперировать можно только ссылками и объектами. А в обработчике ПриЗаписи на сервере признак Проведен уже отражает новое состояние, но движения ещё могут быть не зафиксированы — для анализа движений используйте ОбработкаПроведения или читайте регистры после завершения транзакции.
Сравнение способов и контроль результата
Выбор способа зависит от контекста: что у вас есть на входе, сколько документов проверяется и где выполняется код. Сводная таблица поможет быстро сориентироваться.
| Способ | Когда применять | Стоимость | Ограничение |
|---|---|---|---|
Объект.Проведен | Объект уже получен для других действий | Бесплатно, данные в памяти | Требует ПолучитьОбъект() |
Ссылка.Проведен | Разовая проверка одной ссылки | Один запрос к базе | Не для циклов |
| Запрос с полем Проведен | Массовая проверка, отборы, отчёты | Один запрос на всю выборку | Только данные из базы, не из формы |
Объект.Проведен в форме | Логика интерфейса, доступность кнопок | Без серверного вызова | Может отличаться от базы при параллельном редактировании |
Как проверить результат
Истина — документ проведён и делает движения
Ложь, хотя в интерфейсе документ выглядит проведённым — проверьте, ту ли ссылку читаете
Проверка тысячи документов одним запросом занимает доли секунды
Цикл с ПолучитьОбъект() или Ссылка.Проведен выполняется десятки секунд
Результат проверки совпадает с пиктограммой документа в списке
Расхождение — вероятно, читается устаревший объект или другая ссылка
После выбора способа обязательно проверьте код на трёх состояниях: проведённый документ, непроведённый и помеченный на удаление. Такой минимальный набор покрывает все варианты значения признака и позволяет сразу увидеть ошибки в логике условий.
Часто задаваемые вопросы
Можно ли проверить проведение документа без запроса и без ПолучитьОбъект()?
Да, для одиночной ссылки достаточно обращения Ссылка.Проведен — платформа сама обратится к базе и вернёт значение поля. Это оптимально для разовой проверки. Для множества документов такой приём не подходит, потому что каждое обращение порождает отдельный запрос.
Почему Проведен возвращает Ложь у документа, который выглядит проведённым?
Чаще всего вы проверяете другую ссылку или устаревший объект в памяти, который не перечитывался после изменений. Реже документ был помечен на удаление — пометка снимает проведение. Перечитайте объект или выполните запрос по конкретной ссылке и убедитесь, что сравниваете одни и те же данные.
Как проверить, проведён ли документ, найденный по номеру?
Сначала получите ссылку через Документы.ИмяДокумента.НайтиПоНомеру(Номер, Дата), проверьте её на пустоту через Ссылка.Пустая(), а затем обратитесь к полю Проведен — напрямую через точку или запросом. Без проверки на пустую ссылку обращение к полю вернёт неопределённый результат для несуществующего документа.
Что возвращает Проведен у помеченного на удаление документа?
Всегда Ложь: при установке пометки удаления платформа отменяет проведение. Если в логике нужно отличать «просто не проведён» от «помечен», проверяйте дополнительно поле ПометкаУдаления — оба поля доступны и у объекта, и в запросе.
Можно ли проверить возможность проведения, не проводя документ?
Штатного метода «проверить без проведения» нет. Практикуют два подхода: записать с режимом Проведение внутри попытки и перехватить исключение, либо выполнить проведение в транзакции с последующей отменой. Оба способа реально изменяют данные на время выполнения, поэтому применять их следует осторожно и только там, где без этого не обойтись.
Работает ли проверка Проведен в фоновом задании?
Да, в фоновых заданиях и на сервере доступны все способы: свойство объекта, обращение через ссылку и запросы. Недоступна только работа с данными формы, поскольку формы в фоновом контексте не существует.
Что важно запомнить
Признак проведения хранится в поле Проведен. Для объекта и одиночной ссылки читайте его напрямую, для массовых проверок используйте запрос. Помеченный на удаление документ всегда не проведён. Не используйте ПолучитьОбъект() только ради проверки признака — это лишняя нагрузка на базу.