В процессе разработки на платформе 1С:Предприятие часто возникает задача сохранить настройки пользователя или параметры алгоритмов непосредственно в базе данных. Одной из таких задач является хранение системных перечислений, например, ВидСравнения, ТипБулев или ОбходРезультатаЗапроса. Проблема заключается в том, что в конфигураторе нельзя напрямую выбрать системное перечисление в качестве типа данных для реквизита справочника или документа.
В этой статье мы подробно разберем несколько проверенных способов решения этой задачи, проанализируем их плюсы и минусы, а также выберем наиболее подходящий вариант для различных ситуаций.
Рассмотрим самый надежный и удобный для пользователя способ — создание «суррогатного» или «зеркального» перечисления в дереве метаданных. Этот метод часто используется в типовых конфигурациях (например, в БСП).
Суть метода заключается в создании собственного объекта метаданных, который повторяет структуру системного перечисления. Разберем по шагам:
Перечисление, назовем его, например, ВидыСравненияДляНастроек.Равно, НеРавно, ВСписке и так далее. Имена значений лучше делать идентичными системным.Посмотрим на пример кода функции-конвертера:
Функция ПолучитьСистемныйВидСравнения(ЗначениеНашегоПеречисления) Экспорт
Если ЗначениеНашегоПеречисления = Перечисления.ВидыСравненияДляНастроек.Равно Тогда
Возврат ВидСравнения.Равно;
ИначеЕсли ЗначениеНашегоПеречисления = Перечисления.ВидыСравненияДляНастроек.Больше Тогда
Возврат ВидСравнения.Больше;
// ... и так далее для всех нужных значений
КонецЕсли;
КонецФункции
Преимущества: строгая типизация, возможность выбора значения пользователем из стандартного выпадающего списка, стабильная работа в запросах. Недостатки: необходимость вручную поддерживать актуальность списка значений.
Проанализируем более гибкий подход, который не требует создания новых объектов метаданных. Мы можем хранить строковое представление имени значения перечисления.
Для реализации этого способа создадим реквизит справочника с типом Строка (длиной 50–100 символов). При записи значения будем сохранять имя, а при чтении — восстанавливать объект по имени.
Рассмотрим подробнее реализацию:
// Сохранение значения
ИмяЗначения = Строка(ТекущийВидСравнения);
ОбъектСправочника.РеквизитВидСравнения = ИмяЗначения;
// Восстановление значения
Попытка
НужныйВид = ВидСравнения[ОбъектСправочника.РеквизитВидСравнения];
Исключение
НужныйВид = ВидСравнения.Равно; // Значение по умолчанию
КонецПопытки;
Этот метод очень удобен, когда нужно хранить значения разных системных типов в одном поле (если использовать тип ЛюбаяСсылка или строку). Однако помните, что Строка(ВидСравнения.Равно) вернет локализованное представление (например, "Равно"), что может зависеть от языка сеанса. Для надежности лучше использовать XMLСтрока(Значение).
Выясним, как можно использовать возможности платформы по сериализации данных. Метод XMLСтрока и СериализаторXDTO позволяют превратить системный объект в строку, которую легко сохранить в базе.
Посмотрим на пример использования XMLСтрока:
// Запись в реквизит справочника
Объект.РеквизитХранилище = XMLСтрока(ВидСравнения.МеньшеИлиРавно);
// Чтение из реквизита
// Нам нужно знать тип, чтобы восстановить значение
Значение = XMLЗначение(Тип("ВидСравнения"), Объект.РеквизитХранилище);
Важный нюанс: использование СериализаторXDTO будет еще более универсальным, так как он сохраняет информацию о типе внутри XML-пакета. Это полезно, если в одном реквизите могут лежать разные системные перечисления.
Разберем самый экономный с точки зрения объема данных способ. Каждое системное перечисление имеет порядковый индекс. Мы можем хранить этот индекс в реквизите с типом Число.
Пример реализации работы с индексами:
// Сохраняем индекс
ИндексЗначения = ВидСравнения.Индекс(ВыбранныйВидСравнения);
Объект.РеквизитИндекс = ИндексЗначения;
// Получаем значение обратно
НужныйВид = ВидСравнения.Получить(Объект.РеквизитИндекс);
Внимание: данный способ считается рискованным, так как теоретически при обновлении платформы индексы системных перечислений могут измениться. Хотя для таких базовых типов, как ВидСравнения, это крайне маловероятно, для критически важных систем лучше использовать строковые идентификаторы или зеркальные перечисления.
Если системное перечисление является частью сложной настройки и вам не нужно использовать этот реквизит в условиях запросов или для фильтрации в списках, можно использовать тип ХранилищеЗначения.
Проанализируем ситуацию: мы просто упаковываем объект «как есть».
// Помещение в хранилище
Объект.РеквизитХранилище = Новый ХранилищеЗначения(ВидСравнения.ВСписке);
// Извлечение
ВидСравненияИзБазы = Объект.РеквизитХранилище.Получить();
Этот метод полностью избавляет от необходимости писать функции преобразования, но делает данные абсолютно «непрозрачными» для консоли запросов или стандартных отчетов.
Подводя итог нашему анализу, дадим конкретные рекомендации:
XMLСтрока.Важное примечание: Всегда проверяйте, какой именно «вид сравнения» вам нужен. Системное перечисление ВидСравнения используется в построителе отчетов и динамических списках, в то время как для Системы Компоновки Данных (СКД) необходимо использовать ВидСравненияКомпоновкиДанных. Эти типы не взаимозаменяемы напрямую!