При разработке прикладных решений нередко возникает задача размещения на форме объекта (например, справочника Номенклатура) множества дополнительных параметров в виде логических переключателей и флажков (от 50 до 100 и более). Попытка жестко связать каждый элемент с жестко заданными индексами массивов или последовательный поиск элементов через НайтиПоКоду() внутри циклов приводит либо к падению производительности, либо к ошибкам при добавлении новых реквизитов.
Разберем основные проблемы, возникающие при реализации такой задачи, и рассмотрим наиболее надежные и быстрые способы организации хранения и загрузки данных.
Проанализируем типичные ошибки при чтении данных из регистра сведений:
Флажок1 = ТЗ[0].Значение, при появлении нового свойства или при отсутствии записей по конкретной номенклатуре программа вызовет исключение выхода за границы массива.НайтиПоКоду() или НайтиПоНаименованию() на каждой итерации выборки генерирует избыточные запросы к базе данных, что существенно замедляет открытие формы.Наиболее простое и быстрое решение — использовать прямую адресацию к реквизитам или элементам формы через квадратные скобки. В качестве идентификатора опции в регистре сведений можно хранить строковое имя реквизита/элемента либо связать код предопределенного элемента плана видов характеристик с именем элемента на форме.
Посмотрим на пример процедуры чтения данных для обычной формы в конфигурациях на платформе 1С:
Процедура ЗаполнитьФлагиНаФорме()
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ЗначенияДопОпций.Опция КАК ИмяРеквизита,
| ЗначенияДопОпций.Значение КАК Значение
|ИЗ
| РегистрСведений.ЗначенияДопОпций КАК ЗначенияДопОпций
|ГДЕ
| ЗначенияДопОпций.Номенклатура = &Номенклатура";
Запрос.УстановитьПараметр("Номенклатура", ЭтотОбъект.Ссылка);
РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();
Пока Выборка.Следующий() Цикл
// Обращаемся к реквизиту формы по строковому имени
Попытка
ЭтаФорма[Выборка.ИмяРеквизита] = Выборка.Значение;
Исключение
// Исключение перехватывает случаи, когда реквизит был удален из формы
КонецПопытки;
КонецЦикла;
КонецПроцедуры
Если используется связка с планом видов характеристик, рекомендуется один раз перед циклом выгрузить соответствие кодов ПВХ и реквизитов формы в объект Соответствие, избегая вызовов поиска внутри цикла.
Частая ошибка при записи 70–80 значений — использование объекта СоздатьМенеджерЗаписи() в цикле с вызовом Записать() на каждом шаге. Это порождает десятки отдельных транзакций и обращений к СУБД.
Для оптимизации записи разберем по шагам создание набора записей регистра сведений:
СоздатьНаборЗаписей() для целевого регистра.Номенклатура.Записать().
Процедура СохранитьФлагиВРегистр()
Набор = РегистрыСведений.ЗначенияДопОпций.СоздатьНаборЗаписей();
Набор.Отбор.Номенклатура.Установить(ЭтотОбъект.Ссылка);
// Перебираем элементы или реквизиты формы
Для Каждого ЭлементСписка Из СписокИменФлагов Цикл
ИмяФлага = ЭлементСписка.Значение;
ЗначениеФлага = ЭтаФорма[ИмяФлага];
// Оптимизация: сохраняем только включенные флаги
Если ЗначениеФлага = Истина Тогда
Запись = Набор.Добавить();
Запись.Номенклатура = ЭтотОбъект.Ссылка;
Запись.Опция = ИмяФлага;
Запись.Значение = Истина;
КонецЕсли;
КонецЦикла;
// Единая транзакция записи в СУБД
Набор.Записать();
КонецПроцедуры
Рассмотрим другие архитектурные подходы, которые позволяют упростить поддержку при постоянном расширении списка опций:
СвойстваОбъектов и регистр ЗначенияСвойствОбъектов. Использование типовых подсистем избавляет от необходимости писать собственный код для хранения и отображения свойств.Структура и сохранить в один реквизит номенклатуры типа ХранилищеЗначения.