В процессе разработки на платформе 1С:Предприятие 8.3 программисты часто сталкиваются с особым классом значений — системными (интерфейсными) перечислениями. Примерами таких перечислений являются ВариантУправленияВысотойТаблицы, ВертикальноеПоложение, ВариантВыравниванияЭлементовИЗаголовков и многие другие. Главная сложность заключается в том, что эти объекты отсутствуют в дереве метаданных конфигурации, а стандартный СериализаторXDTO зачастую отказывается работать с ними напрямую, выдавая ошибки при попытке записи в XML или JSON.
Разберем детально, как решить задачу сохранения таких значений в файл или базу данных и, что не менее важно, как корректно восстановить их обратно. Мы проанализируем несколько подходов: от классических внутренних функций до наиболее современных и надежных методов.
Рассмотрим типичную ситуацию. Нам необходимо сохранить настройки формы, где фигурирует системный тип. Казалось бы, достаточно использовать стандартный механизм:
Запись = Новый ЗаписьXML;
Запись.УстановитьСтроку();
СериализаторXDTO.ЗаписатьXML(Запись, ЗначениеСистемногоПеречисления);
ТекстXML = Запись.Закрыть();
Однако для большинства интерфейсных перечислений этот код вызовет исключение. Платформа 1С не считает их полноценными объектами метаданных, поэтому стандартные схемы XDTO для них не всегда определены. Нам приходится искать обходные пути. Выясним, какие варианты у нас есть.
Проанализируем наиболее элегантный и надежный способ, который был предложен опытными разработчиками. Метод ПолучитьПолноеИмяПредопределенногоЗначения() позволяет получить строковую идентификацию объекта, которая не зависит от языка интерфейса пользователя (локализации).
Преимущества этого метода:
ИмяПеречисления.ИмяЗначения (например, ВариантУправленияВысотойТаблицы.Авто).Вычислить() или через поиск в коллекции.Посмотрим на пример реализации сохранения:
ЗначениеДляСохранения = ВариантУправленияВысотойТаблицы.ВСтрокахТаблицы;
ИмяЗначения = ПолучитьПолноеИмяПредопределенногоЗначения(ЗначениеДляСохранения);
// В итоге в ИмяЗначения будет строка "ВариантУправленияВысотойТаблицы.ВСтрокахТаблицы"
Для восстановления значения из такой строки мы можем использовать следующий код:
Попытка
ВосстановленноеЗначение = Вычислить(ИмяЗначения);
Исключение
ВосстановленноеЗначение = Неопределено;
КонецПопытки;
Хотя методы ЗначениеВСтрокуВнутр() и ЗначениеИзСтрокиВнутр() считаются устаревшими и их не рекомендуют использовать для обмена между разными информационными базами, в рамках одной базы они работают безотказно уже много лет. Рассмотрим этот механизм как быстрый вариант для временного хранения.
Проанализируем ситуацию: если вам нужно сохранить настройки в текстовый файл и быстро их прочитать обратно в той же версии платформы, этот метод будет самым коротким в плане написания кода:
// Сохранение
СтрокаСериализации = ЗначениеВСтрокуВнутр(ЗначениеПеречисления);
// Восстановление
Попытка
ЗначениеПеречисления = ЗначениеИзСтрокиВнутр(СтрокаСериализации);
Исключение
// Обработка ошибки формата
КонецПопытки;
Важный нюанс: формат внутреннего представления 1С может быть чувствителен к версии платформы, поэтому для долгосрочного хранения или передачи данных во внешние системы лучше выбрать другой способ.
Выясним причину, по которой некоторые разработчики предпочитают хранить индекс значения. Каждое системное перечисление является коллекцией, которую можно обойти циклом Для каждого. Мы можем сохранить тип перечисления и порядковый номер выбранного элемента.
Алгоритм действий:
Рассмотрим программную реализацию поиска индекса:
Функция ПолучитьИндексСистемногоПеречисления(Значение)
Тип = ТипЗнч(Значение);
// Для системных перечислений можно использовать конструктор ОписаниеТипов
// или получить доступ к коллекции через имя типа
Коллекция = Вычислить(Строка(Тип));
Индекс = 0;
Для каждого Элемент Из Коллекция Цикл
Если Элемент = Значение Тогда
Возврат Индекс;
КонецЕсли;
Индекс = Индекс + 1;
КонецЦикла;
Возврат -1;
КонецФункции
Внимание: помните о рисках! Как было отмечено в обсуждении, индексы системных перечислений могут измениться при обновлении платформы 1С. Если разработчики платформы добавят новое значение в середину списка, ваши сохраненные индексы "поплывут". Используйте этот метод с осторожностью.
Если нам нужно гарантировать восстановление даже в случае изменения платформы, проанализируем вариант сохранения структуры данных. Сохраним тип, строковое представление (на языке пользователя) и английский идентификатор.
Рассмотрим пример кода для подготовки данных к выгрузке:
ДанныеДляХранения = Новый Структура;
ДанныеДляХранения.Вставить("ТипСтрокой", Строка(ТипЗнч(Значение)));
ДанныеДляХранения.Вставить("Представление", Строка(Значение));
ДанныеДляХранения.Вставить("ПолноеИмя", ПолучитьПолноеИмяПредопределенногоЗначения(Значение));
// Сериализуем структуру в JSON или XML стандартными средствами
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку();
ЗаписатьJSON(ЗаписьJSON, ДанныеДляХранения);
Результат = ЗаписьJSON.Закрыть();
При восстановлении мы сначала попробуем использовать ПолноеИмя. Если оно не сработает (например, значение переименовано), мы сможем выполнить перебор коллекции и сравнить строковые представления, чтобы найти наиболее подходящий вариант. Это обеспечит максимальную отказоустойчивость вашего кода.
Подведем итоги нашего анализа. Для надежной работы с несериализуемыми системными перечислениями в 1С:
Применяя эти подходы, мы сможем эффективно сохранять настройки интерфейса и другие параметры, использующие специфические типы данных 1С.