Как в форме подбора 1С запретить выбор групп (папок) номенклатуры и исправить ошибку «Преобразование к значению тип Булево не может быть выполнено»?

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

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

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

Проанализируем сначала причины ошибок, которые возникли у автора темы на форуме, а затем перейдем к правильным алгоритмам реализации.

---

Почему возникают ошибки при проверке «ЭтоГруппа»?

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

Ошибка 1. «Переменная не определена (ЭтоГруппа)» на клиенте.
Автор пытался написать проверку напрямую в клиентском обработчике выбора строки:


&НаКлиенте
Процедура СписокВыбор(Элемент, ВыбраннаяСтрока, Поле, СтандартнаяОбработка)
    СтандартнаяОбработка = Ложь;
    Если ЭтоГруппа Тогда // Ошибка! Переменная не определена
        Сообщить("Ошибка");
    КонецЕсли;
КонецПроцедуры

Выясним причину: директива &НаКлиенте указывает платформе, что этот код выполняется на стороне пользователя (в тонком или веб-клиенте). На клиенте нет непосредственного доступа к базе данных. Платформа ничего не знает о реквизитах справочника номенклатуры, пока мы явно не обратимся к объекту базы данных. Просто написать слово ЭтоГруппа в контексте формы нельзя — форма «не понимает», к какому именно объекту относится это свойство.

Ошибка 2. «Тип не определен (Запрос)» на клиенте.
Пытаясь обойти предыдущую проблему, разработчик решил написать запрос прямо на клиенте. Однако в управляемом приложении 1С любые запросы к базе данных (объект Запрос) могут выполняться исключительно на сервере. Попытка создать объект через Новый Запрос на клиенте всегда будет приводить к аварийному завершению работы программы.

Ошибка 3. «Преобразование к значению тип Булево не может быть выполнено».
Эта ошибка возникла, когда автор попытался перенести проверку на сервер, создав следующую функцию:


&НаСервере
Функция ГруппаЭто(СсылкаНоменклатуры)
    Если СсылкаНоменклатуры.ЭтоГруппа Тогда
        Возврат ИСТИНА;
    КонецЕсли;
КонецФункции

И вызывая её на клиенте:

Если ГруппаЭто(ВыбраннаяСтрока) Тогда ...

Разберем по шагам, что здесь произошло:

  1. Если пользователь выбирает группу (папку), условие Если СсылкаНоменклатуры.ЭтоГруппа выполняется, функция возвращает значение Истина. Код на клиенте работает корректно.
  2. Если пользователь выбирает элемент (товар), условие Если СсылкаНоменклатуры.ЭтоГруппа возвращает Ложь. Программа перескакивает блок внутри условия и доходит до конца функции.
  3. Поскольку функция завершила работу, но оператор Возврат не был выполнен для этого случая, функция по умолчанию возвращает значение Неопределено.
  4. На клиенте выражение превращается в Если Неопределено Тогда. Платформа 1С не может неявно преобразовать тип Неопределено к логическому типу (Булево) и выдает критическую ошибку выполнения.

---

Вариант решения №1. Декларативный метод (без написания кода)

Самый простой и правильный с точки зрения архитектуры 1С способ — настроить форму так, чтобы пользователь физически не мог выбрать группу. В этом случае нам вообще не придется писать программные проверки!

Рассмотрим, как это сделать:

Способ А. Через свойства элемента формы

  1. Откроем конфигуратор и найдем форму подбора (или форму списка справочника Номенклатура, которая используется для выбора).
  2. Найдем таблицу, отображающую список номенклатуры (как правило, это элемент формы, связанный с динамическим списком).
  3. В панели свойств этого элемента (таблицы) найдем категорию «Использование».
  4. Установим свойство «Выбор групп и элементов» в значение «Элементы» (вместо значения «Группы и элементы»).

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

Способ Б. Через параметры открытия формы подбора

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


&НаКлиенте
Процедура ОткрытьПодбор(Команда)
    ПараметрыПодбора = Новый Структура;
    // Ограничиваем выбор только элементами
    ПараметрыПодбора.Вставить("ВыборГруппИЭлементов", ИспользованиеГруппИЭлементов.Элементы);
    
    ОткрытьФорму("Справочник.Номенклатура.Форма.ФормаВыбора", ПараметрыПодбора, ЭтаФорма);
КонецПроцедуры

---

Вариант решения №2. Оптимальный программный метод без вызова сервера

Если вам по какой-то причине всё же нужно обрабатывать выбор группы программно (например, выводить пользователю предупреждение «Выбор папок запрещен!»), делать это с помощью серверных вызовов крайне не рекомендуется. Каждый вызов сервера — это сетевой запрос, который снижает скорость работы интерфейса.

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

Разберем этот метод по шагам:

  1. В форме подбора выберем основной реквизит формы (обычно это Список с типом ДинамическийСписок).
  2. В окне свойств этого реквизита нажмем кнопку открытия настройки списка (свойство «Настройка списка») или перейдем в его свойства. Нам нужно убедиться, что поле ЭтоГруппа всегда передается на клиент.
  3. В свойствах поля ЭтоГруппа внутри динамического списка установим флаг «Использовать всегда».
  4. В обработчике выбора строки напишем следующий клиентский код:

&НаКлиенте
Процедура СписокВыбор(Элемент, ВыбраннаяСтрока, Поле, СтандартнаяОбработка)
    // Отменяем стандартное действие платформы, чтобы форма выбора не закрылась автоматически
    СтандартнаяОбработка = Ложь;
    
    // Получаем данные текущей строки, которые уже кэшированы на клиенте
    ТекущиеДанные = Элементы.Список.ТекущиеДанные;
    
    Если ТекущиеДанные <> Неопределено Тогда
        // Проверяем свойство ЭтоГруппа без обращения к серверу
        Если ТекущиеДанные.ЭтоГруппа Тогда
            ПоказатьПредупреждение(, "Выбор группы (папки) запрещен! Пожалуйста, выберите товар.");
            Возврат;
        КонецЕсли;
        
        // Ниже идет ваш рабочий код добавления элемента в список подбора
        Стр = ВыбранныеТовары.Добавить();
        Стр.Номенклатура = ВыбраннаяСтрока;
        Стр.Количество = 1;
    КонецЕсли;
КонецПроцедуры

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

---

Вариант решения №3. Правильный серверный метод (с исправлением ошибок приведения типов)

Если данные проверяются в контексте, где нет динамического списка (например, вы проверяете переданную ссылку в произвольной таблице), вам действительно придется обратиться к серверу. Посмотрим, как сделать это правильно, избежав ошибок приведения к Булево и оптимизировав нагрузку на систему.

Ниже представлен правильный шаблон реализации:


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

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

Проанализируем ключевые особенности этого серверного кода:

---

Резюме

Мы детально разобрали особенности работы со свойством ЭтоГруппа в формах подбора 1С. Для обеспечения максимального быстродействия и простоты поддержки конфигурации придерживайтесь следующих правил:

  1. Всегда отдавайте предпочтение декларативной настройке интерфейса (свойство «Выбор групп и элементов» = «Элементы»), так как это базовый механизм платформы.
  2. Если требуется программная обработка, используйте чтение свойства ЭтоГруппа через ТекущиеДанные динамического списка на клиенте.
  3. Если серверный вызов неизбежен, всегда объявляйте функции с директивой &НаСервереБезКонтекста и следите за тем, чтобы функция при любых условиях возвращала корректное логическое значение (Истина или Ложь).
← На главную