Как реализовать инженерный калькулятор с динамическим набором параметров в 1С?

Программист 1С v8.3 (Управляемые формы) Промышленность, строительство и АПК
← На главную

При разработке конфигураций и подсистем для производственных предприятий часто возникает задача расчета геометрических или технологических параметров изделий (например, площади воздуховодов, отводов, тройников или врезок). Каждое изделие обладает уникальным набором исходных размеров и собственной формулой расчета, однако в учете все они должны выступать позициями номенклатуры. Рассмотрим, как грамотно спроектировать структуру данных, организовать пользовательский интерфейс и оптимизировать математические расчеты в управляемом приложении 1С.

Анализ архитектурных подходов и типичные ошибки

Перед тем как приступать к коду, проанализируем возможные варианты архитектуры и выясним, с какими проблемами можно столкнуться при неверном выборе:

  1. Разделение на независимые справочники под каждый тип изделия. Если создать справочники Справочник.Отводы, Справочник.Заглушки, Справочник.Воздуховоды, то во всех документах конфигурации (заказах, накладных, спецификациях) придется использовать реквизиты составного типа. Это приводит к существенному замедлению работы СУБД, невозможности построения компактных индексов, затруднениям при контроле остатков и громоздким отчетам. Поэтому базовая сущность должна оставаться единым справочником Номенклатура.
  2. Использование функциональных опций на форме объекта. Функциональные опции в платформе 1С кэшируются на уровне сеанса и предназначены для включения или отключения глобальных подсистем (например, многовалютного учета или учета по складам). Управлять видимостью полей конкретного элемента внутри одной открытой формы через функциональные опции технически невозможно.
  3. Использование модели EAV (План видов характеристик + Регистр сведений). Универсальный подход с программным добавлением реквизитов и элементов управления через ПВХ оправдан только тогда, когда состав параметров постоянно меняется пользователями в режиме «1С:Предприятие». Если формулы и состав характеристик стабильны, такая схема создает избыточную нагрузку на базу данных из-за множества запросов при открытии формы и записи, а также неоправданно усложняет валидацию введенных значений.

Оптимальное решение для интерфейса: переключение страниц формы

Если количество типов изделий ограничено (порядка 10–15 видов) и формулы расчета фиксированы, наиболее надежным и быстрым вариантом является размещение полей на скрытых страницах формы. Разберем по шагам, как это реализовать:

  1. В справочнике Номенклатура создаем реквизит ВидИзделия с типом перечисления (или ссылкой на фиксированный классификатор).
  2. На форму элемента добавляем группу с видом Страницы. Для свойства ОтображениеЗакладок устанавливаем значение Не отображать.
  3. Внутри группы создаем отдельные страницы под каждый вид изделия: СтраницаОтводКруглый, СтраницаТройник, СтраницаЗаглушка.
  4. На каждую страницу перетаскиваем только те реквизиты, которые требуются для расчета конкретного узла.
  5. Вместо медленного построчного перебора видимости отдельных элементов (Элементы.Поле.Видимость = Ложь) переключаем всю страницу одной командой через свойство ТекущаяСтраница.

Посмотрим на пример обработчика изменения вида изделия на клиенте:


&НаКлиенте
Процедура ВидИзделияПриИзменении(Элемент)
    УстановитьСтраницуПараметров();
КонецПроцедуры

&НаКлиенте
Процедура УстановитьСтраницуПараметров()
    
    Если Объект.ВидИзделия = ПредопределенноеЗначение("Перечисление.ВидыИзделий.ОтводКруглый") Тогда
        Элементы.ГруппаСтраницПараметров.ТекущаяСтраница = Элементы.СтраницаОтводКруглый;
    ИначеЕсли Объект.ВидИзделия = ПредопределенноеЗначение("Перечисление.ВидыИзделий.ТройникПрямоугольный") Тогда
        Элементы.ГруппаСтраницПараметров.ТекущаяСтраница = Элементы.СтраницаТройникПрямоугольный;
    ИначеЕсли Объект.ВидИзделия = ПредопределенноеЗначение("Перечисление.ВидыИзделий.Заглушка") Тогда
        Элементы.ГруппаСтраницПараметров.ТекущаяСтраница = Элементы.СтраницаЗаглушка;
    Иначе
        Элементы.ГруппаСтраницПараметров.ТекущаяСтраница = Элементы.СтраницаПоУмолчанию;
    КонецЕсли;

КонецПроцедуры

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

Хранение параметров: табличная часть или сериализация JSON

Чтобы не создавать в таблице справочника десятки разреженных колонок (где для отвода заполнен диаметр, а высота и ширина остаются пустыми), рассмотрим два практичных метода хранения:

  1. Табличная часть справочника. Создаем табличную часть ПараметрыИзделия с колонками ИмяПараметра (Строка) и Значение (Число). При открытии формы значения из таблицы переносятся в реквизиты формы, а перед записью выгружаются обратно. Запись данных происходит в одной транзакции с самим объектом без обращения к сторонним регистрам.
  2. Сериализация в JSON. Все параметры сохраняются в строковый реквизит неограниченной длины. Для чтения и записи используем встроенные средства платформы: функции ПрочитатьJSON и ЗаписатьJSON. При открытии формы строка преобразуется в структуру, значения из которой заполняют поля на форме.

Организация инженерных расчетов без громоздких условий

Инженерные формулы часто содержат коэффициенты, зависящие от углов поворота или типоразмеров. Нагромождение условий Если ... ИначеЕсли снижает читаемость кода и провоцирует ошибки. Рассмотрим расчет площади круглого отвода, где промежуточные параметры определяются углом изделия:


&НаСервереБезКонтекста
Функция РассчитатьПлощадьОтводаКруглого(Диаметр, Угол) Экспорт

    ЧислоПи = 3.1415926535;
    
    // Подготовка таблицы технологических коэффициентов
    ПараметрыУглов = Новый Соответствие;
    ПараметрыУглов.Вставить(90, Новый Структура("ЧислоЗвеньев, ДелительШейки", 2, 2));
    ПараметрыУглов.Вставить(60, Новый Структура("ЧислоЗвеньев, ДелительШейки", 2, 3));
    ПараметрыУглов.Вставить(45, Новый Структура("ЧислоЗвеньев, ДелительШейки", 0, 4));
    ПараметрыУглов.Вставить(30, Новый Структура("ЧислоЗвеньев, ДелительШейки", 0, 6));
    ПараметрыУглов.Вставить(15, Новый Структура("ЧислоЗвеньев, ДелительШейки", 0, 12));
    
    ДанныеУгла = ПараметрыУглов[Угол];
    Если ДанныеУгла = Неопределено Тогда
        ВызватьИсключение "Недопустимый угол отвода: " + Формат(Угол, "ЧГ=0");
    КонецЕсли;
    
    ЧислоЗвеньев = ДанныеУгла.ЧислоЗвеньев;
    ДелительШейки = ДанныеУгла.ДелительШейки;
    
    Шейка = (ЧислоПи / ДелительШейки * Диаметр / 2) / (ЧислоЗвеньев + 2) + 15;
    Срез  = (ЧислоПи / ДелительШейки * Диаметр) / (ЧислоЗвеньев * 2 + 2);
    
    ПлощадьS2 = ЧислоПи * Диаметр / 1000 * 0.1;
    ПлощадьS1 = (ЧислоПи * Диаметр * (2 * (Шейка + Срез / 2) + ЧислоЗвеньев * (Шейка + Срез))) / 1000000;
    
    Возврат Окр(ПлощадьS1 + ПлощадьS2, 4);

КонецФункции

Важное архитектурное правило: расчетные функции следует размещать в модуле менеджера справочника или в общем серверном модуле. Это позволит повторно использовать алгоритм не только на форме элемента, но и при групповом пересчете спецификаций, импорте данных из CAD-систем или выполнении регламентных заданий без контекста клиентской формы.

← На главную