Как эффективно хранить и загружать большое количество флажков на форме в 1С

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

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

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

Проблема 1. Медленная загрузка и хрупкость жесткой индексации

Проанализируем типичные ошибки при чтении данных из регистра сведений:

  1. Обращение по фиксированным индексам строк: если привязать элементы вида Флажок1 = ТЗ[0].Значение, при появлении нового свойства или при отсутствии записей по конкретной номенклатуре программа вызовет исключение выхода за границы массива.
  2. Поиск ссылки в цикле выборки: выполнение методов НайтиПоКоду() или НайтиПоНаименованию() на каждой итерации выборки генерирует избыточные запросы к базе данных, что существенно замедляет открытие формы.

Решение 1. Динамическая загрузка данных по имени реквизита

Наиболее простое и быстрое решение — использовать прямую адресацию к реквизитам или элементам формы через квадратные скобки. В качестве идентификатора опции в регистре сведений можно хранить строковое имя реквизита/элемента либо связать код предопределенного элемента плана видов характеристик с именем элемента на форме.

Посмотрим на пример процедуры чтения данных для обычной формы в конфигурациях на платформе 1С:


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

Если используется связка с планом видов характеристик, рекомендуется один раз перед циклом выгрузить соответствие кодов ПВХ и реквизитов формы в объект Соответствие, избегая вызовов поиска внутри цикла.

Решение 2. Пакетное сохранение через Набор записей вместо Менеджера

Частая ошибка при записи 70–80 значений — использование объекта СоздатьМенеджерЗаписи() в цикле с вызовом Записать() на каждом шаге. Это порождает десятки отдельных транзакций и обращений к СУБД.

Для оптимизации записи разберем по шагам создание набора записей регистра сведений:

  1. Создаем объект СоздатьНаборЗаписей() для целевого регистра.
  2. Устанавливаем отбор по ведущему измерению Номенклатура.
  3. Заполняем набор только теми опциями, значение которых равно Истина (это уменьшает объем базы данных и ускоряет чтение).
  4. Выполняем однократный вызов метода Записать().

Процедура СохранитьФлагиВРегистр()
    
    Набор = РегистрыСведений.ЗначенияДопОпций.СоздатьНаборЗаписей();
    Набор.Отбор.Номенклатура.Установить(ЭтотОбъект.Ссылка);
    
    // Перебираем элементы или реквизиты формы
    Для Каждого ЭлементСписка Из СписокИменФлагов Цикл
        ИмяФлага = ЭлементСписка.Значение;
        ЗначениеФлага = ЭтаФорма[ИмяФлага];
        
        // Оптимизация: сохраняем только включенные флаги
        Если ЗначениеФлага = Истина Тогда
            Запись = Набор.Добавить();
            Запись.Номенклатура = ЭтотОбъект.Ссылка;
            Запись.Опция = ИмяФлага;
            Запись.Значение = Истина;
        КонецЕсли;
    КонецЦикла;
    
    // Единая транзакция записи в СУБД
    Набор.Записать();
    
КонецПроцедуры

Решение 3. Альтернативные варианты отображения и хранения

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

  1. Использование элемента управления «Табличное поле»: вместо размещения 80 отдельных флажков на форме размещается одно табличное поле, привязанное к дереву или таблице значений. В колонке флага устанавливается свойство отображения флажка. Это позволяет пользователям сортировать опции, выполнять поиск по наименованию и группировать их по категориям, а разработчику — не перерисовывать макет формы при добавлении новых свойств.
  2. Штатный механизм дополнительных реквизитов: в типовых конфигурациях (например, УПП, Комплексная автоматизация) уже реализован встроенный механизм СвойстваОбъектов и регистр ЗначенияСвойствОбъектов. Использование типовых подсистем избавляет от необходимости писать собственный код для хранения и отображения свойств.
  3. Хранение структуры в реквизите типа «ХранилищеЗначения»: если флажки носят исключительно информационный характер и по ним не требуется строить сложные аналитические отчеты с отборами в запросах, весь набор состояний можно упаковать в объект Структура и сохранить в один реквизит номенклатуры типа ХранилищеЗначения.
← На главную