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