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

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

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

Разбор типичных ошибок в коде

Рассмотрим ситуацию, с которой часто сталкиваются начинающие программисты. Допустим, у нас есть поле ввода на форме, где выбран документ, и кнопка, которая должна сообщить о его статусе. Часто код выглядит примерно так:


&НаСервере
Процедура Ответ(Поступление)
    НайдДок = Объект.Поступление.ПолучитьОбъект();
    Если НайдДок.Проведен Тогда
        Сообщить("Документ проведён!");
    Иначе 
        Сообщить("Документ НЕ проведён!");
    КонецЕсли;
КонецПроцедуры

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

Во-вторых, обратите внимание на логику передачи данных. Если мы передаем в процедуру параметр Поступление, то внутри процедуры следует обращаться именно к этому параметру, а не к Объект.Поступление. Смешивание контекста формы и переданных параметров часто ведет к трудноуловимым ошибкам.

Вариант 1. Самый простой (обращение через точку)

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


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

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

Вариант 2. Использование запроса (Оптимальный для производительности)

Проанализируем ситуацию с точки зрения высоконагруженных систем. Самый правильный и быстрый способ узнать значение конкретного поля в базе данных — это выполнить Запрос. В этом случае СУБД (например, SQL Server) вернет нам ровно один бит информации (истина/ложь), не затрагивая остальные данные документа.


&НаСервере
Функция ДокументПроведенЗапрос(СсылкаНаДокумент)
    
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |   ДокументПоступления.Проведен КАК Проведен
        |ИЗ
        |   Документ.ПоступлениеТоваровУслуг КАК ДокументПоступления
        |ГДЕ
        |   ДокументПоступления.Ссылка = &Ссылка";
    
    Запрос.УстановитьПараметр("Ссылка", СсылкаНаДокумент);
    
    РезультатЗапроса = Запрос.Выполнить();
    
    Если РезультатЗапроса.Пустой() Тогда
        Возврат Ложь; // Документ не найден
    КонецЕсли;
    
    Выборка = РезультатЗапроса.Выбрать();
    Выборка.Следующий();
    
    Возврат Выборка.Проведен;
    
КонецФункции

Такой подход считается "золотым стандартом" разработки на 1С, особенно если проверка выполняется в фоновых заданиях или при обработке больших массивов данных.

Вариант 3. Использование Библиотеки стандартных подсистем (БСП)

Если ваша конфигурация построена на базе БСП (а это почти все современные типовые решения, такие как УТ 11, ERP, БП 3.0), то разработчики уже предусмотрели готовые инструменты. Выясним, как использовать метод ЗначениеРеквизитаОбъекта.

Этот метод внутри себя уже содержит оптимизированный запрос и механизмы кэширования, что делает ваш код чище и быстрее:


// Пример использования функций общего модуля БСП
Статус = ОбщегоНазначения.ЗначениеРеквизитаОбъекта(Объект.Поступление, "Проведен");

Если Статус = Истина Тогда
    Сообщить("Документ проведен!");
КонецЕсли;

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

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


&НаСервере
Процедура ПроверитьСостояние(Ссылка)
    
    // Получаем сразу два реквизита одним запросом через БСП
    Данные = ОбщегоНазначения.ЗначенияРеквизитовОбъекта(Ссылка, "Проведен, ПометкаУдаления");
    
    Если Данные.ПометкаУдаления Тогда
        Сообщить("Документ находится в корзине (помечен на удаление)");
    ИначеЕсли Данные.Проведен Тогда
        Сообщить("Документ активен и проведен");
    Иначе
        Сообщить("Документ просто записан, но не проведен");
    КонецЕсли;
    
КонецПроцедуры

Как связать это с кнопкой на форме?

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


&НаКлиенте
Процедура КомандаПроверить(Команда)
    
    // Проверяем заполнение поля на форме
    Если Объект.Поступление.Пустая() Тогда
        Предупреждение("Пожалуйста, выберите документ!");
        Возврат;
    КонецЕсли;
    
    // Вызываем серверную функцию
    Результат = ПолучитьИнформациюОПроведении(Объект.Поступление);
    
    // Выводим ответ пользователю
    Сообщить(Результат);
    
КонецПроцедуры

&НаСервереБезКонтекста
Функция ПолучитьИнформациюОПроведении(Ссылка)
    // Используем "БезКонтекста" для ускорения вызова
    Если Ссылка.Проведен Тогда
        Возврат "Документ проведен успешно!";
    Иначе
        Возврат "Документ не проведен.";
    КонецЕсли;
КонецФункции

Подведем итоги

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

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

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

← На главную