Как программно проверить, заполнено ли дополнительное сведение в 1С:Бухгалтерия 3.0?

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

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

Проанализируем исходный код и разберем несколько способов решения этой задачи: от простой проверки результата запроса до использования стандартных функций Библиотеки стандартных подсистем (БСП).

Анализ исходной ситуации

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

Посмотрим на ее код:


Функция ПолучитьЗначениеДопСведений(Ссылка, Свойство) Экспорт

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

КонецФункции

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

Способ 1: Проверка результата запроса

Самый прямой способ решения — это проверить, вернул ли запрос вообще какие-либо строки. Сделать это можно двумя популярными методами.

Метод А: Проверка на пустоту

У объекта РезультатЗапроса есть метод Пустой(), который возвращает Истина, если выборка не содержит ни одной записи. Это самый лаконичный способ.

Модифицируем нашу функцию:


Функция ПолучитьЗначениеДопСведений(Ссылка, Свойство) Экспорт

    Запрос = Новый Запрос;
    // ... текст запроса тот же ...
    Запрос.УстановитьПараметр("Объект", Ссылка);
    Запрос.УстановитьПараметр("Имя", Свойство);

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

КонецФункции

Теперь функция явно возвращает Неопределено, если значение не найдено. В вызывающем коде можно легко проверить результат: Если ПолученноеЗначение = Неопределено Тогда ....

Метод Б: Проверка через итератор Следующий()

Это более классический и универсальный подход, который часто используется при работе с выборками. Метод Следующий() пытается перейти к следующей записи и возвращает Истина, если это удалось, и Ложь, если записей больше нет. Если вызвать его один раз для новой выборки, мы как раз и проверим, есть ли в ней хотя бы одна запись.

Давайте посмотрим на этот вариант:


Функция ПолучитьЗначениеДопСведений(Ссылка, Свойство) Экспорт

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

КонецФункции

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

Способ 2: Использование стандартных функций БСП (Рекомендуемый подход)

В современных конфигурациях, построенных на Библиотеке стандартных подсистем (БСП), к которой относится и "1С:Бухгалтерия 3.0", существуют готовые инструменты для работы с дополнительными реквизитами и сведениями. Использовать их — лучшая практика, так как это делает код более универсальным, читаемым и устойчивым к будущим обновлениям конфигурации. Вам не нужно писать прямые запросы, вся логика уже инкапсулирована в общем модуле УправлениеСвойствами.

Ключевая функция, которая нам понадобится — УправлениеСвойствами.ЗначениеСвойства().

Давайте разберем по шагам, как ей пользоваться.

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

Посмотрим на пример кода:


// Предположим, у нас есть СсылкаНаОбъект (например, на элемент справочника "Контрагенты")
// И нам нужно проверить заполненность сведения с именем "НашМенеджер"

// 1. Находим само свойство в Плане Видов Характеристик
ИмяНужногоСвойства = "НашМенеджер";
НужноеСвойство = ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.НайтиПоНаименованию(ИмяНужногоСвойства);

// Проверяем, найдено ли такое свойство в системе вообще
Если НужноеСвойство.Пустая() Тогда
    Сообщить("Свойство с именем '" + ИмяНужногоСвойства + "' не найдено в системе!");
    Возврат;
КонецЕсли;

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

// 3. Проверяем, заполнено ли значение
Если ЗначениеЗаполнено(ЗначениеСведения) Тогда
    Сообщить("Дополнительное сведение '" + ИмяНужногоСвойства + "' заполнено. Его значение: " + Строка(ЗначениеСведения));
Иначе
    Сообщить("Дополнительное сведение '" + ИмяНужногоСвойства + "' не заполнено.");
КонецЕсли;

Почему этот способ лучше?

Важное уточнение: Дополнительные реквизиты vs. Дополнительные сведения

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

В рассмотренной теме речь шла именно о дополнительных сведениях, так как использовался регистр ДополнительныеСведения.

В заключение, для проверки заполненности дополнительного сведения можно использовать как прямой запрос с проверкой результата, так и стандартные функции БСП. Хотя первый способ работает, настоятельно рекомендуется использовать функции общего модуля УправлениеСвойствами для написания чистого, надежного и поддерживаемого кода.

← На главную