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