Можно ли получить имена полей формы и состав групп в общем модуле на сервере?

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

В практике разработки на платформе 1С:Предприятие часто возникают задачи, требующие динамического формирования текста запроса. Один из сценариев, с которым мы можем столкнуться — это необходимость собрать запрос на основании тех полей, которые пользователь видит на форме в определенной группе. Например, в конфигурации 1С:ERP существует справочник СкладскиеЯчейки, где поля адресации (Секция, Линия, Стеллаж, Ярус, Позиция) сгруппированы визуально.

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

Суть проблемы: Доступ к элементам формы на сервере

Рассмотрим ситуацию. У нас есть общий модуль с галочкой "Сервер". В нем выполняется процедура, которая должна получить список имен полей, входящих в группу "Адресация" формы элемента справочника. Автор вопроса пытался использовать метод получения формы, чтобы добраться до ее элементов.

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

Важно понимать разделение контекста:

  1. Форма — это объект интерфейса. Элементы формы (поля, группы, кнопки) существуют и "живут" преимущественно на клиенте.
  2. Объект/Данные — это сущность базы данных. На сервере мы работаем с данными (СправочникОбъект, ДокументОбъект) или коллекциями данных.

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

Таким образом, прямой ответ на вопрос: нет, в общем модуле на сервере невозможно получить доступ к дереву элементов формы (Элементы.ИмяГруппы.ПодчиненныеЭлементы), если эта информация не была передана с клиента.

Почему привязка к полям формы — это плохая идея?

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

Давайте рассмотрим риски такого подхода:

Правильные способы решения задачи

Разберем альтернативные подходы, которые позволяют реализовать динамическую сборку запроса без привязки к элементам формы.

Способ 1. Использование Метаданных (Самый надежный)

Вместо того чтобы смотреть на форму, мы должны смотреть на структуру самой конфигурации — Метаданные. Если нам нужно получить все реквизиты, отвечающие за адресацию, мы можем перебрать все реквизиты справочника и отобрать нужные по определенному признаку (например, по имени или типу).

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


Функция ПолучитьПоляАдресацииДляЗапроса() Экспорт
    
    СписокПолей = Новый Массив;
    
    // Получаем описание метаданных справочника
    МетаданныеСправочника = Метаданные.Справочники.СкладскиеЯчейки;
    
    // Ключевые слова, по которым мы ищем поля адресации
    // Либо можно перечислить точные имена: "Секция", "Линия", "Стеллаж"
    КлючевыеИмена = Новый Структура("Секция, Линия, Стеллаж, Ярус, Позиция");
    
    Для Каждого Реквизит Из МетаданныеСправочника.Реквизиты Цикл
        
        // Проверяем, входит ли имя реквизита в наш список интересов
        Если КлючевыеИмена.Свойство(Реквизит.Имя) Тогда
            СписокПолей.Добавить(Реквизит.Имя);
        КонецЕсли;
        
    КонецЦикла;
    
    Возврат СписокПолей;
    
КонецФункции

Этот подход устойчив к изменениям формы. Если вы добавите новый реквизит в конфигураторе, вам достаточно добавить его имя в структуру проверки (или использовать префикс в именовании, например, Адрес_Секция, тогда код вообще не придется менять).

Способ 2. Передача параметров из формы (Если контекст есть)

Если процедура общего модуля вызывается из модуля формы, то проблему решить легко. Форма "знает" о своих элементах. Мы можем собрать нужные данные на клиенте или в контекстном серверном вызове формы и передать их в общий модуль.

Алгоритм действий:

  1. В модуле формы создаем структуру или массив.
  2. Обходим коллекцию Элементы.ГруппаАдресация.ПодчиненныеЭлементы.
  3. Заполняем массив именами путей к данным (ПутьКДанным).
  4. Передаем этот готовый массив в процедуру общего модуля.

Пример кода в модуле формы:


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

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

Способ 3. Использование настроек топологии (Специфика ERP)

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

В ERP состав адресации (используется ли ярус, используется ли стеллаж) зависит от настроек конкретного складского помещения. Поэтому самым правильным, "методологическим" решением будет:

  1. Получить ссылку на текущий склад или помещение.
  2. Прочитать настройки использования разрезов (обычно это булевы реквизиты: ИспользоватьСекции, ИспользоватьСтеллажи и т.д.).
  3. На основании этих настроек (значений Истина/Ложь) добавлять поля в текст запроса.

Давайте посмотрим, как это логически выглядит:


// Пример логики (имена реквизитов могут отличаться в разных версиях ERP)
СтруктураПолей = Новый Структура;
Если СкладскоеПомещение.ИспользоватьСекции Тогда
    СтруктураПолей.Вставить("Секция");
КонецЕсли;
Если СкладскоеПомещение.ИспользоватьПозиции Тогда
    СтруктураПолей.Вставить("Позиция");
КонецЕсли;

// Далее собираем запрос по ключам структуры

Резюме

Подведем итог нашему разбору:

Используя эти подходы, вы сделаете свой код надежным, предсказуемым и независимым от капризов настройки пользовательского интерфейса.

← На главную