Как правильно сравнить значение перечисления и управлять видимостью элементов в 1С

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

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

Почему сравнение со строкой не работает?

Проанализируем ситуацию: в метаданных конфигурации создан реквизит Операция. Скорее всего, он имеет тип ПеречислениеСсылка.ТипыОпераций (или аналогичный). В пользовательском интерфейсе мы видим слова «Выдача» или «Возврат», однако для системы это не текст, а ссылка на конкретный объект в базе данных. Когда мы пишем Объект.Операция = "Выдача", мы пытаемся сравнить сложный объект (ссылку) с примитивным типом (строкой). Система 1С всегда вернет Ложь, так как это разные типы данных.

Рассмотрим пример того, как делать не рекомендуется:


// Неправильный подход
Если СокрЛП(Строка(Объект.Операция)) = "Выдача" Тогда
    // Код может сработать, но это плохая практика
КонецЕсли;

Почему это плохо? Во-первых, функция Строка() работает медленно, так как требует обращения к метаданным для получения синонима. Во-вторых, если ваша конфигурация будет переведена на другой язык, синоним перечисления изменится (например, на "Issue"), и ваш код перестанет работать. Всегда нужно сравнивать ссылки, а не их текстовые представления.

Использование функции ПредопределенноеЗначение

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

Разберем, как должен выглядеть правильный синтаксис сравнения:


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

Обратите внимание: путь к значению внутри кавычек должен полностью соответствовать метаданным (Перечисление.ИмяПеречисления.ИмяЗначения).

Различие между данными и элементами формы

Второй критической ошибкой в исходном коде является обращение к свойству Видимость через структуру Объект. Давайте выясним причину, по которой это не работает. В управляемом приложении 1С существует четкое разделение между:

  1. Данными (Объект): это реквизиты, которые хранятся в базе данных или временных структурах (числа, строки, даты, таблицы). У них нет свойств «Видимость», «Доступность» или «Цвет».
  2. Интерфейсом (Элементы): это визуальные компоненты формы (поля ввода, кнопки, таблицы, группы). Именно у элементов есть свойство Видимость.

Чтобы скрыть или показать поле или таблицу на форме, мы должны обращаться к коллекции Элементы. Например, если у вас на форме есть табличная часть с именем «Книги», обращение к ней должно выглядеть так: Элементы.Книги.Видимость = Истина;.

Оптимальный алгоритм управления видимостью

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


&НаКлиенте
Процедура ОперацияПриИзменении(Элемент)
    
    // Определяем текущее состояние через булевы переменные
    ЭтоВыдача = (Объект.Операция = ПредопределенноеЗначение("Перечисление.ТипыОпераций.Выдача"));
    ЭтоВозврат = (Объект.Операция = ПредопределенноеЗначение("Перечисление.ТипыОпераций.Возврат"));
    
    // Устанавливаем видимость элементов напрямую
    Элементы.Книги.Видимость = ЭтоВыдача;
    Элементы.КнигиПлюс.Видимость = ЭтоВозврат;
    
КонецПроцедуры

В данном примере мы исключаем ошибки наслоения интерфейса. Если пользователь сначала выбрал «Выдачу», а затем передумал и выбрал «Возврат», первая таблица автоматически скроется, так как условие ЭтоВыдача станет Ложь.

Важность установки состояния при открытии формы

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

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


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    // Устанавливаем видимость при открытии существующего объекта
    УстановитьВидимостьЭлементов();
КонецПроцедуры

&НаКлиенте
Процедура ОперацияПриИзменении(Элемент)
    // Устанавливаем видимость при изменении значения пользователем
    УстановитьВидимостьЭлементов();
КонецПроцедуры

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

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

Для корректной работы с логикой переключений в 1С важно соблюдать три правила:

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

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

← На главную