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

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

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

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

Задача проверить состояние документа возникает почти в каждой доработке: перед вызовом проведения, при построении отчёта, при обмене данными или при блокировке изменений. В 1С:Предприятии 8 у документа есть два разных состояния, которые часто путают: документ может быть записан (существовать в базе данных) и может быть проведён (иметь движения по регистрам). Это не одно и то же, и проверяются они по-разному.

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

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

Чем «записан» отличается от «проведён»

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

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

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

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

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

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

// Документ проведён

Иначе

// Документ записан, но не проведён

КонецЕсли;

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

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

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

Когда объекта нет, а есть только ссылка (например, документ выбран в параметре отчёта или пришёл из другой процедуры), свойство доступно и через ссылку:

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

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

КонецЕсли;

Здесь кроется главный подводный камень производительности. Обращение к любому реквизиту через ссылку выполняет неявный запрос к базе данных. Одно обращение — не страшно, но в цикле по тысяче документов вы получите тысячу отдельных запросов. Такой код на больших объёмах работает медленно и нагружает СУБД.

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

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

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

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

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

"ВЫБРАТЬ

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

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

|ИЗ

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

|ГДЕ

| РеализацияТоваровУслуг.Ссылка В (&СписокДокументов)";

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

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

Такой запрос выполняется один раз и возвращает состояние всех документов из списка. Результат удобно выгрузить в таблицу значений и дальше работать с ней в памяти без обращений к базе.

Порядок массовой проверки
  1. 1
    Соберите ссылки проверяемых документов в массив или список значений
  2. 2
    Сформируйте запрос к таблице документа с выборкой полей Ссылка и Проведен
  3. 3
    Передайте список в параметр и выполните запрос один раз
  4. 4
    Выгрузите результат в таблицу значений и обрабатывайте её в цикле
  5. 5
    Для каждой строки проверяйте значение поля Проведен

Запросом же удобно отбирать сразу только проведённые или только непроведённые документы, добавив условие ГДЕ Проведен или ГДЕ НЕ Проведен. Это типовой приём при построении отчётов и обработок сверки.

Проверка в обработчиках событий

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

Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)

Если РежимЗаписи = РежимЗаписиДокумента.Проведение

И НЕ Проведен Тогда

// Документ проводится впервые

КонецЕсли;

КонецПроцедуры

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

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

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

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

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

Если ДокументОбъект.ЭтоНовый() Тогда

// Документ ещё не записан в базу

КонецЕсли;

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

Частые ошибки и ограничения

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

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

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

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

Контрольные точки

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

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

Истина для проведённого, Ложь для записанного без проведения

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

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

Наличие движений по регистрам
Норма

У проведённого документа есть записи хотя бы в одном регистре

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

Проведен = Истина, но движений нет — возможно, проведение отключено в обмене или очищено обработкой

Скорость массовой проверки
Норма

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

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

В замере производительности виден запрос на каждую итерацию цикла

FAQ

Чем отличается проверка Проведен у объекта и у ссылки?

Функционально — ничем, результат одинаков. Разница в производительности: у объекта свойство читается из памяти, а обращение через ссылку выполняет запрос к базе. В циклах используйте объект или отдельный запрос.

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

Объедините выборки через ОБЪЕДИНИТЬ ВСЕ, выбирая Ссылка и Проведен из каждой таблицы документов. Либо, если документы связаны общим реквизитом или критерием отбора, постройте запрос по критерию отбора.

Почему Проведен возвращает Ложь, хотя документ точно проведён?

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

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

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

Как в типовой конфигурации проверить существование документа по ссылке?

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

Итог

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

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