Можно ли вызвать процедуру из общей формы в СКД?

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

При разработке отчетов на базе Системы компоновки данных (СКД) разработчики часто сталкиваются с необходимостью выполнить специфическую логику, которая уже реализована в какой-либо форме. Возникает вопрос: можно ли напрямую обратиться к процедуре или функции, объявленной в модуле общей формы, непосредственно из выражений СКД? В этой статье мы подробно разберем, почему прямой вызов невозможен, и рассмотрим все существующие способы обхода этого ограничения.

Почему прямой вызов процедуры формы из СКД невозможен?

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

Разберем основные причины ограничения:

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

Таким образом, на вопрос «Можно ли вызвать процедуру из формы?» ответ — нет. Однако мы можем перенести логику в те места, откуда СКД сможет её «дотянуться».

Решение 1: Использование функций общих модулей

Это самый правильный и рекомендуемый стандарт разработки в 1С. Если логика универсальна и может понадобиться в СКД, её следует вынести в общий модуль. Проанализируем, как это сделать правильно, чтобы СКД «увидела» вашу функцию.

Во-первых, общий модуль должен иметь установленный флаг «Сервер». Во-вторых, для использования в выражениях СКД функция обязательно должна быть экспортной. Рассмотрим пример функции, которую мы хотим вызвать в вычисляемом поле:


// В общем модуле "РаботаСОтчетами"
Функция ПолучитьКоэффициентСложности(IDОбъекта) Экспорт
    // Здесь ваша логика, которая раньше была в форме
    Возврат 1.25; 
КонецФункции

Чтобы вызвать эту функцию в СКД (например, в поле «Выражение» на закладке «Вычисляемые поля»), нужно использовать синтаксис: ИмяОбщегоМодуля.ИмяФункции(Параметры). В нашем случае это будет выглядеть так:

РаботаСОтчетами.ПолучитьКоэффициентСложности(Ссылка)

Важный нюанс: Если вы используете конфигурацию на управляемых формах, убедитесь, что у модуля не стоит флаг «Глобальный», иначе обращение будет идти без точки, что может вызвать путаницу в именах. Лучше всегда использовать явное указание имени модуля.

Решение 2: Вызов из модуля объекта отчета

Если логика специфична только для конкретного отчета и вы не хотите загромождать общие модули, можно использовать модуль объекта самого отчета. Мало кто знает, что СКД умеет обращаться к экспортным функциям своего «родителя».

Рассмотрим порядок действий:

  1. Перейдите в модуль объекта вашего отчета.
  2. Определите там функцию с ключевым словом Экспорт.
  3. В схеме компоновки данных в поле выражения просто напишите имя функции без каких-либо префиксов.

// В модуле объекта отчета
Функция РассчитатьДополнительныйПоказатель(Сумма) Экспорт
    Возврат Сумма * 0.15;
КонецФункции

В СКД в вычисляемом поле просто укажем: РассчитатьДополнительныйПоказатель(СуммаПродаж). Платформа сама найдет эту функцию в контексте выполняемого отчета.

Решение 3: Использование внешних наборов данных

Иногда процедура в форме настолько сложна и так сильно зависит от текущего состояния экранных форм (например, введенных пользователем данных в таблицу на форме), что перенести её в модуль невозможно. В этом случае мы используем механизм «Внешний набор данных».

Проанализируем этот алгоритм:

  1. В форме отчета создаем процедуру, которая готовит данные.
  2. Результат вычислений помещаем в Таблицу Значений.
  3. Передаем эту таблицу в процессор компоновки данных непосредственно перед формированием отчета.

Пример программного формирования с внешним набором данных в модуле формы:


&НаСервере
Процедура СформироватьНаСервере()
    // 1. Получаем данные из нашей процедуры формы
    ТаблицаРезультат = ПолучитьДанныеИзЛогикиФормы(); 
    
    // 2. Инициализируем компоненты СКД
    Схема = Отчеты.МойОтчет.ПолучитьМакет("ОсновнаяСхемаКомпоновкиДанных");
    Настройки = Отчет.КомпоновщикНастроек.ПолучитьНастройки();
    
    ДанныеРасшифровки = Новый ДанныеРасшифровкиКомпоновкиДанных;
    КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
    МакетКомпоновки = КомпоновщикМакета.Выполнить(Схема, Настройки, ДанныеРасшифровки);
    
    // 3. Передаем внешнюю таблицу
    ВнешниеНаборыДанных = Новый Структура;
    ВнешниеНаборыДанных.Вставить("МояТаблица", ТаблицаРезультат);
    
    ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
    ПроцессорКомпоновки.Инициализировать(МакетКомпоновки, ВнешниеНаборыДанных, ДанныеРасшифровки);
    
    // 4. Выводим результат в табличный документ
    Результат = Элементы.Результат;
    Результат.Очистить();
    ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
    ПроцессорВывода.УстановитьДокумент(Результат);
    ПроцессорВывода.Вывести(ПроцессорКомпоновки);
КонецПроцедуры

В этом сценарии СКД вообще не вызывает форму. Наоборот — форма подготавливает данные и «скармливает» их системе компоновки.

Ограничения типов и контекста

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

Типы возвращаемых значений: Функции, вызываемые из СКД, должны возвращать простые типы (Число, Строка, Дата, Булево) или Ссылки. Если ваша функция в форме возвращала Структуру или Массив, то при переносе в модуль для целей СКД её придется переделать. СКД не сможет отобразить структуру в ячейке отчета и выдаст ошибку.

Веб-клиент и мобильный клиент: Если вы переносите логику из формы в общий модуль, следите за тем, чтобы там не осталось методов, доступных только на клиенте (например, Предупреждение() или Вопрос()). СКД работает на сервере, и наличие таких методов приведет к падению отчета.

Резюме

Подведем итог. Напрямую вызвать процедуру из общей формы из СКД невозможно из-за разницы контекстов исполнения (Сервер vs Интерфейс). Для решения задачи выберите один из трех путей:

Наиболее чистым и поддерживаемым решением является вынос расчетной логики в неглобальный общий модуль с установленным флагом «Сервер».

← На главную